May 282017
 

To program the ESP32 is usually a bit of luck and sometimes pressing the reset button if you’re less lucky.

RTS and/or DTR should be able to reset the ESP32. Once it’s reliably reset, a download via netcat works. If I only had a program to reset RTS and/or DTR!

I found one here, changed it to toggle DTR instead of RTS as toggling RTS did not do anything. Now I can reset the ESP32 reliably. Full automation is achieved!

Here the DTR toggle program:

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


static struct termios oldterminfo;


void closeserial(int fd)
{
 tcsetattr(fd, TCSANOW, &oldterminfo);
 if (close(fd) < 0)
 perror("closeserial()");
}


int openserial(char *devicename)
{
 int fd;
 struct termios attr;

 if ((fd = open(devicename, O_RDWR)) == -1) {
 perror("openserial(): open()");
 return 0;
 }
 if (tcgetattr(fd, &oldterminfo) == -1) {
 perror("openserial(): tcgetattr()");
 return 0;
 }
 attr = oldterminfo;
 attr.c_cflag |= CRTSCTS | CLOCAL;
 attr.c_oflag = 0;
 if (tcflush(fd, TCIOFLUSH) == -1) {
 perror("openserial(): tcflush()");
 return 0;
 }
 if (tcsetattr(fd, TCSANOW, &attr) == -1) {
 perror("initserial(): tcsetattr()");
 return 0;
 }
 return fd;
}


int setSerial(int fd, int bitmask, int level)
{
 int status;

 if (ioctl(fd, TIOCMGET, &status) == -1) {
 perror("setSerial(): TIOCMGET");
 return 0;
 }
 if (level)
 status |= bitmask;
 else
 status &= ~bitmask;
 if (ioctl(fd, TIOCMSET, &status) == -1) {
 perror("setSerial(): TIOCMSET");
 return 0;
 }
 return 1;
}


int main(int argc, char *argv[])
{
 int fd;
 char *serialdev = "/dev/ttyUSB0";
 int bitmask;

 if (argc == 2) {
 serialdev = argv[1];
 }

 // printf("device: %s\n", serialdev);


 fd = openserial(serialdev);
 if (!fd) {
 fprintf(stderr, "Error while initializing %s.\n", serialdev);
 return 1;
 }

 bitmask = TIOCM_DTR; // alternatively TIOCM_RTS | TIOCM_DTR

 setSerial(fd, bitmask, 0);
 sleep(1); /* pause 1 second */
 setSerial(fd, bitmask, 1);

 closeserial(fd);
 return 0;
}

And the program to upload to the ESP (via netcat):

#!/bin/bash 
# 
# Upload JS file to ESP32 via wifi 
# 
# Usage: 
# uploadesp.sh JAVASCRIPTFILE IPADDRESS 
 
if [[ $# -ne 2 ]] ; then 
        echo "Usage: $0 JAVASCRIPTFILE IPADDRESS" 
        exit 20 
fi 
 
if [[ ! -f "$1" ]] ; then 
        echo "ERROR: Cannot read file \"$1\"" 
        exit 10 
fi 
 
dtr-toggle 
 
TMP="$(mktemp).js" 
espruino -n -o $TMP $1 
echo "Uploading to $2:23" 
nc $2 23 < $TMP >/dev/null 
 
# rm $TMP 
exit 0

 

May 282017
 
ESP32 and Espruino

Those ESP modules and Espruino are a very attractive combination. The latest one I ordered is particularily nice: ESP32 with plenty RAM (512 KB), 2 cores, with a 128×64 pixel OLED, plus Espruino. Sweet!

./esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 \
  --before default_reset --after hard_reset write_flash \
  -z --flash_mode qio --flash_freq 80m --flash_size detect \
  0x1000 /tmp/espruino_1v92.71_esp32/bootloader.bin \
  0x8000 /tmp/espruino_1v92.71_esp32/partitions_espruino.bin \
  0x10000 ../Espruino/espruino_esp32.bin

The bootloader.bin and partitions_espruino.bin come from the Travis cutting-edge builds. The binary I compiled from https://github.com/espruino/Espruino

Connecting via Web IDE works usually. In case of problems, use minicom to connect (115200 baud). Pushing the reset button always works. At this point the Web IDE will connect too.

Uploading code via Web IDE works. 100% reliable as far as I can say. But I wanted a command line uploads to do things like TypeScript and use make or Jenkins for build, test, upload cycles.

https://www.npmjs.com/package/espruino is a NPM modules for NodeJS which makes this possible. However direct uploads via serial port (/dev/ttyUSB0) does not work reliable (<10% success). Turns out there’s a better way:

#!/bin/bash
# Usage: uploadesp.sh JAVASCRIPT_FILE.js IP_OF_ESP32 
TMP=$(mktemp)
espruino -n -o $TMP $1
nc $2 23 < $TMP >/dev/null

That’s 100% working so far and much, much faster to upload. Note that the espruino command (actually espruino-cli.js) needs some changes to recognize the -n option to not talk to the serial interface.

Update: dio and 40MHz works fine too.

May 212017
 

ESP8285

Espruino does not need more than 1 MB of Flash memory, so using a single chip solution with 1 MB Flash integrated like the ESP8285 seesm to be a sensible choice. And it works with Espruino just like the ESP8266 does.

The only special part is how to flash it:

esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash \
--flash_mode dout --flash_size 8m \
0x0000 boot_v1.6.bin \
0x1000 espruino_esp8266_user1.bin \
0xFC000 esp_init_data_default.bin 0xFE000 blank.bin

There’s no difference when it comes to save(): only very small programs can be saved. I hope the ESP32 is better in this regard.