ESP8266 VGA OUTPUT

This is a VGA library for ESP8266.
To use this library you need only 1 resistor and one DSUB15 connector.
VGA signal generation based on https://github.com/hchunhui/esp-vga (thanks for your awesome works).
[….]

The library implement a 512x480px framebuffer with 1bpp, where each pixel is stored as a single bit. The framebuffer is stored inside RAM and require 30720 bytes.

Posted in Esp8266, Retro Computing | Tagged | Comments Off on ESP8266 VGA OUTPUT

esp8266 micropython uasyncio experimental build

Esp8266 is the super cheap chip which can run Micropython. You can buy it on Amazon for as little as €8 or less, and as little as $5 or less on Bangood/AliExpress.

The ESP8266 (ESP-12E spec) has a 4MB Flash RAM and about 96KB of  RAM. 

One nice thing is you can use an async mode easily  and it works great. So I took this very good complete tutorial on asyncio, and hacked a bit the micropython source code to offer to you a super-breeze async version
First of all I taken the last version of Micropython (1.10) and started to push to its limit to offer at least 44Kb to the interpreter. 51Kb is the theoretical limit, but you must left some space for the interpreter to work correctly.
To increase Micropython available memory, you must download Micropython source code and hack it. It is a bit complex, so a Linux machine is recommended, anyway I managed to to it on a Windows10 with linux subsystem (WSL) which is a bit slow but it is a nice environemnt to work with.
On this forum [1]  I found some specific information, then I forked micropython code base (below you will find my proposed modifications, also a pre-made image is provided).

Overview

First of all edit heap size in main.c
This step needs a bit of caution, because the interpreter needs RAM to work correctly, but you can try to grab a few kilobytes

// From 36Kb....
STATIC char heap[36 * 1024];
// to whoppy 44Kb
STATIC char heap[44 * 1024];

Then we will liste all the C modules pre-compiled, using the help function:

>>> help('modules')
__main__          hashlib           socket            upip
_boot             inisetup          ssl               upip_utarfile
_onewire          io                struct            urandom
_webrepl          json              sys               ure
apa102            lwip              time              uselect
array             machine           uasyncio/__init__ usocket
binascii          math              uasyncio/core     ussl
btree             micropython       ubinascii         ustruct
builtins          neopixel          ucollections      utime
collections       network           ucryptolib        utimeq
dht               ntptime           uctypes           uzlib
ds18x20           onewire           uerrno            webrepl
errno             os                uhashlib          webrepl_setup
esp               port_diag         uheapq            websocket
flashbdev         random            uio               websocket_helper
framebuf          re                ujson             zlib
gc                select            uos

Now the best way is to “scaffold” your micropython for the final target use. For instance I do not plan to use neopixel or frameuffers, because my little esp8266 will act like a server for tuning stuff on and off.

Also webrepl and websocket could be ripped off. At the end of my work, I ended with the following module list

__main__          io                struct            uos
_boot             json              sys               upip
_onewire          lwip              time              upip_utarfile
apa102            machine           uasyncio/__init__ urandom
array             math              uasyncio/core     ure
binascii          micropython       uasyncio/queues   uselect
builtins          network           uasyncio/synchro  usocket
collections       ntptime           ubinascii         ussl
dht               onewire           ucollections      ustruct
ds18x20           os                ucryptolib        utime
errno             port_diag         uctypes           utimeq
esp               random            uerrno            uzlib
flashbdev         re                uhashlib          websocket
gc                select            uheapq            websocket_helper
hashlib           socket            uio               zlib
inisetup          ssl               ujson

I have prepared a forked git hub repository with my hacks [3]: look at the  daitan-hacks branch.

 

Download the ready made image!

  1. “Super Expander” version (Work in progress) 40Kb with basic uasyncio and no webrepl
  2. esp8266-experimental-v1.10.bin.zip Simpler version with asyncio and more RAM

Reference

[1] https://forum.micropython.org/viewtopic.php?t=4813 
[2] Micropython reference
[3] GitHub source

 

Posted in Esp8266 | Tagged , , , , | Comments Off on esp8266 micropython uasyncio experimental build

esp8266 webImport

UPDATED and BUGFIXED!

MicroPython Repl command line is very nice, because you can telnet to the chip and read-and-evaluate python code. It is a great way of learning embedded IoT. The bad thing you cannot copy file while it is running, so experimenting get bad.

Also an automatic module update would be a very nice thing to have.

So I have created a small module called webImport which is able to

  1. download a module.py from a known http server
  2. write it in the esp8266 and import it
  3. enable your esp8266 to be hacked by a worm :) (see below for caveats)

The idea is to serve your remote module via a HTTP server and load it on the repl (or programmatically) with

from webimport import web_import
web_import('modulename')

After a while you edit your modulename.py and you make a newMethod. So you want to reload it…with…

web_import('modulename')
modulename.method()

The CODE

The code is below and was tested on esp8266. It should work on Pyboard and more powerful board too.

# Implement a web import api
# Rev 1.0.2
# Rev 1.0.1  was bugged 
#import ujson as json
import uos as os
import usocket as socket

debug=True

def say(m):
    if debug:
        print("wi: "+str(m))
    

def extractHeaders(headers_pair2split):    
    hp=headers_pair2split.split(b'\r\n')
    headers={}
    for elem in hp:
        k,v=elem.split(b':',1)
        headers[k]=v
        say(str(k)+" => "+str(v))

def http_get_async(url):
    say("webImport:"+url)
    _, _, host, path = url.split('/', 3)
    if ':' in host:
        host, port = host.split(':')
    else:
        port = 80
    addr = socket.getaddrinfo(host, int(port))[0][-1]
    s = socket.socket()
    s.connect(addr)
    s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host),
                 'utf8'))
    headerStr = b''
    body_bytes= b''
    buffer=b''
    ## Skip headerStr: they are tiny, so we get a small chunk
    while True:        
        buffer= buffer + s.recv(250)
        if b'\r\n\r\n' in buffer:
            break
    # Evict headerStr
    headerStr, body_bytes = buffer.split(b'\r\n\r\n',1)
    # GG Consider splitting via b'\r\n' to get headers, get Date:
    # to implement a caching algorithm
    #print("wi: debug: headers:"+str(headerStr)+" SIZE:"+str(len(str(headerStr))))
    response, headers_pair2split=headerStr.split(b'\r\n',1)
    extractHeaders(headers_pair2split)
    if '200 OK' not in response:
        raise ImportError("Response not ok:"+str(response))
    yield body_bytes
    while True:
        data= s.recv(1600)
        if data:
            yield data
        else:
            break

def http_get(url):
    response = b''
    try:
        get = http_get_async(url)
        while True:
            file_bytes = get.send(None)
            response += file_bytes
    except StopIteration:
        pass

    response_str = str(response, 'utf-8')
    return response_str


def ensure_dirs(path):
    split_path = path.split('/')
    if len(split_path) > 1:
        for i, fragment in enumerate(split_path):
            parent = '/'.join(split_path[:-i])
            try:
                os.mkdir(parent)
            except OSError:
                pass


def http_get_to_file(url, path):
    ensure_dirs(path)
    totSize=0
    with open(path, 'w') as outfile:
        try:
            get = http_get_async(url)
            while True:
                file_bytes = get.send(None)
                outfile.write(file_bytes)
                totSize+=len(file_bytes)
        except StopIteration:            
            outfile.close()
            say("Loaded "+path+"#"+str(totSize))




def web_import(moduleName, host="192.168.1.7:8000", on_error_use_cache=True):
    try:
        fname="./"+moduleName+".py"
        url="http://"+host+"/"+fname
        http_get_to_file(url,fname)
        return __import__(moduleName)
    except OSError as e:
        print(str(e))
        if on_error_use_cache:                        
            m= __import__(moduleName)
            print("wi: "+moduleName+" ECONN cache ok")
            return m

 

Optimization

As a bonus you can cross-compile the module, using the MicroPython cross compiler, which runs under any Unix-like system and compiles .py scripts into .mpy files.

https://github.com/micropython/micropython/tree/master/mpy-cross

This step is optional but offer to you less memory usage and better performance

 

Final thoughts

Be warned: having a remote download and execution code is a security risk. Node.js’ Npm package manager face this risk again and again, so you should consider some sort of password protection and / or https authentication using the ussl module which does not protect you but Man in the middle attack.

Posted in English Content, Esp8266, IT Featured | Tagged , | Comments Off on esp8266 webImport

IoT Async

Qualche mese fa avevo sviluppato una applicazione IoT per misurare la temperatura e spedire i dati ad una coda mqtt.
Poi c’era uns server che collezionava i dati.
Totale: tre server, con tre punti di fallimento ma architettura molto “cool”

In effetti però la potenza dei moderni chip embedded è tale che è possibile implementare una soluzione completamente asincrona “alla Erlang”.
Con meno di 8 euro, potete procuravi il chip esp8266 su Amazon

con relativo sensore

e poi sviluppare un servizio micropython che vi notifichi il cambio di temperatura in modo asincrono.

L’idea è che chi è interessato alla temperatura si “registri” sul disposivo IoT con qualcosa come

curl http://esp8266/subTemp/$callerHostname/$desideredPort/$callerRef
# Esempio attualizzato
curl http://esp8266/subTemp/mypc/7001/pushTemp

Dopodiché sarà il dispositivo IoT con i suoi tempi (per esempio dettati dalla funzionalità del sensore, ecc) a fare una chiamata all’ indietro  (callback) del tipo

http://callerHostname:desideredPort/callerRef/$temperature/$humidity
# Esempio attualizzato
http://mypc:7001/pushTemp/23/84

Per semplicità le chiamate sono in GET (benché dovrebbero essere delle POST).

L’agente interessato a tale misure può essere un server scritto in nodejs, python o ruby e può anche richiedere la notifica ad un server terzo (per es esposto su Internet), per es sottoscrivendolo con qualcosa come

curl http://esp8266/subTemp/serverPippo/80/sendTemperatureAndHumidity
Posted in English Content, Erlang, Esp8266 | Comments Off on IoT Async

Esp8266 Music Machine

After months of esp8266 experimentation, I “just” discovered this little chip has also a I2S Audio digital interface. To discover it you must install the Arduino IDE adapter and code directly in C++ (brr, ok not a breeze but not boring like Java :)

I2S is a digital protocol to send your digital  music to a DAC decoder. Esp8266 has a 16bit DAC.

The ESP8266Audio library is a very powerful and dynamic library. You can play a lot of file formats.

The clever part of this library is you need not a DAC circuit: the library come with a delta-sigma DAC emulator, to use a simple transistor to power an analog speaker.

A delta-sigma DAC encodes a high-resolution digital input signal into a lower-resolution but higher sample-frequency signal that is mapped to voltages, and then smoothed with an analog filter. In both cases, the temporary use of a lower-resolution signal simplifies circuit design and improves efficiency.

(From Wikipedia)

To understand Delta Signma look at this article https://hackaday.io/project/6356-delta-sigma-versus-pwm

I just joined this library with the makeEspArduino Makefile, to get a fast compilation cycle.

This because Arduino compilation slow down a lot with this library (it seems to need a huge set of libraries).

Anyway, a very good library you should give a try!

 

References

Posted in English Content, Esp8266 | Tagged , | Comments Off on Esp8266 Music Machine

Esp8266 your WiFi Embedded solution

Arduino is a great hardware for a lot of reason: easy to use, difficulto to break, it is a very solid 5-Volt board.

But it a way too much and it has a very limited amount of RAM. So I started exploring other more “different” solutions.  
I need an economy chip with some RAM on it.
After some research, I stumpled upon a lot of so-called Arduino alternative…

  1. STM 32
    Good price but less support
  2. Teensy
    Very like an Arduino nano, but seems priced a bit too much. Anyway a strong solution in its respect.
  3. Particle Photon
    Priced above Arduino, does not seem particular interesting right now.
  4. PyBoard
    Priced above an Arduino (34€) and based on the STM32F405RGT6.
    PyBoard has 192KB of RAM, but seems a bit too priced.
  5. Beagle Bone
    Priced above a RaspberryPi3, so a no-way in my humble opinion.

And the winner is Esp8266, with a 80Mhz chip with WiFi on board.

The ESP8266 (ESP-12E spec) has a 4MB Flash RAM, about 96KB of  RAM (but some reserved). Uf you put MicroPython on board, you can get very interesting stuff on it (If you remind the BBC Microbit has only 16KB of RAM for running MicroPython, you can understand why esp8266 is an interesting chip)

The only drawback is you have only one analog pin, so be careful if your project need them!

Also you can easily overclock it to 160 Mhz to push its boundaries.

 

You can also find some “clones” at less then 10 euros on Amazon, anyway I suggest this more “safe” version:

 

After some rambling I go to this Micro Python tutorial https://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html
to flash micropython on the newcomer.

Flashing Micropython on Windows

  1. Download your firmware at http://micropython.org/download#esp8266
  2. Install Python 3
  3. Install esptool with pip3.[bash]
    pip3 install esptool
    [/bash]
  4. Under Windows the device is mapped to a COM port like COM1, COM2 etc (a old fashioned ms-dos style port :)
    To find out the correct COM port, I opened my windooze “Hardware” and looked under Ports (COM & LPT).
  5. After finding out your COM port, you can flash the last version of micropython with commands like
    [bash]
    esptool.py –port COM4 erase_flash
    # NodeMCU specific command
    esptool.py –port COM4 –baud 460800 write_flash –flash_size=detect -fm dio 0 esp8266-20170108-v1.8.7.bin
    [/bash]

 

Pins

 

Power

Our little ESP8266 can be powered via the VIN pin.  which support variable voltage up to 20Volt.

 

For more power examples take a look at http://henrysbench.capnfatz.com/henrys-bench/arduino-projects-tips-and-more/powering-the-esp-12e-nodemcu-development-board/

 

Posted in English Content, Esp8266, IT Featured, Knowledgebase | Tagged | Comments Off on Esp8266 your WiFi Embedded solution