Month: October 2022

Trying to fix a MQTT communication issue with NuttX and TagoIO

As you saw in my previous post I was able to get the same mqttc example from NuttX running on Linux.

Unfortunately the NuttX application is not working, then I decided to run the WireShark to compare what the Linux application was doing different from the NuttX application.

It should be easier to sniffer the network if it was Ethernet instead WiFi, so I used the ESP32-Ethernet-Kit board to test with NuttX and a RaspberryPI 3 to test with Linux (I tried to use other computer with Linux, but there are so many packages from Linux services that it was also impossible to compare).

Initially I connected both boards to my WiFi router RJ45 ports, but the router seems to isolate each port, so it is working like an Ethernet Switch instead of working like an Ethernet HUB.

Then I decided to use my laptop to share Internet with those board (one by time). I remember that I did it almost 15 years ago and documented it here (sorry in Portuguese).

That idea worked fine, that is a good solution for future test!

Initially I noticed some strange things: first the NuttX was with “MSS=536” (the minimum MSS size supported by IPv4) where the Linux was using “MSS=1460”

NuttX:
3	0.050060828	192.168.1.100	75.2.83.130	TCP	60	4097 → 1883 [SYN] Seq=0 Win=5488 Len=0 MSS=536

Linux:
7	1.359660410	192.168.1.100	99.83.172.119	TCP	74	40264 → 1883 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=2409185516 TSecr=0 WS=128

Maybe these differences could explain why NuttX was not working, but unfortunately increasing the MSS to 1460 didn’t help, I still receiving a Ack=0 from the server:

6 34.353497310 192.168.1.100 75.2.83.130 TCP 60 4097 → 1883 [SYN] Seq=0 Win=5488 Len=0 MSS=1446
7 34.496251127 75.2.83.130 192.168.1.100 TCP 58 1883 → 4097 [SYN, ACK] Seq=0 Ack=0 Win=65535 Len=0 MSS=0

So, let to test other ideas, I also noticed that the Linux application was using a big Window (Win=64240), the “Selective Acknowledgements” (SACK_PERM=1), time stamp (TSval=2409185516 TSecr=0) and Window Size Scaling (WS=128)

$ sudo sysctl -w net.ipv4.tcp_sack=0
$ sudo sysctl -w net.ipv4.tcp_timestamps=0
$ sudo sysctl -w net.ipv4.tcp_window_scaling=0

These modifications also didn’t solve the issue.

Increasing the Window to 65KB on NuttX doesn’t sound like a good idea, let’s to modify this other Linux TCP stack parameters to become similar to NuttX, we can reduce the Win to 4KB:

# echo "4096 4096 4096" > /proc/sys/net/ipv4/tcp_rmem
# echo "4096 4096 4096" > /proc/sys/net/ipv4/tcp_wmem

Another nice idea is to reduce the MTU to 576 and consequently the MSS becomes 536:

$ sudo ifconfig eth0 mtu 576 up

It also didn’t make the issue show up on Linux, so there is some other detail, see complete Linux log:

1	0.000000000	192.168.1.100	8.8.8.8	DNS	72	Standard query 0x6055 A mqtt.tago.io
2	0.041538839	8.8.8.8	192.168.1.100	DNS	104	Standard query response 0x6055 A mqtt.tago.io A 99.83.172.119 A 75.2.83.130
3	0.043238286	192.168.1.100	99.83.172.119	TCP	60	59880 → 1883 [SYN] Seq=0 Win=1460 Len=0 MSS=1460
4	0.190940161	99.83.172.119	192.168.1.100	TCP	58	1883 → 59880 [SYN, ACK] Seq=0 Ack=1 Win=65535 Len=0 MSS=1416
5	0.191451199	192.168.1.100	99.83.172.119	TCP	60	59880 → 1883 [ACK] Seq=1 Ack=1 Win=1460 Len=0
6	0.192109946	192.168.1.100	99.83.172.119	MQTT	117	Connect Command
7	0.371321172	99.83.172.119	192.168.1.100	TCP	54	1883 → 59880 [ACK] Seq=1 Ack=64 Win=65535 Len=0
8	0.371805531	192.168.1.100	99.83.172.119	MQTT	111	Publish Message [tago/data/post]
9	0.467783276	99.83.172.119	192.168.1.100	MQTT	58	Connect Ack
10	0.468174062	192.168.1.100	99.83.172.119	TCP	60	59880 → 1883 [ACK] Seq=121 Ack=5 Win=1456 Len=0
11	0.515294572	99.83.172.119	192.168.1.100	TCP	54	1883 → 59880 [ACK] Seq=5 Ack=121 Win=65535 Len=0
12	5.098640506	20:7b:d2:0d:a8:d0	Raspberr_65:2a:1a	ARP	42	Who has 192.168.1.100? Tell 192.168.1.1
13	5.099071927	Raspberr_65:2a:1a	20:7b:d2:0d:a8:d0	ARP	60	192.168.1.100 is at b8:27:eb:65:2a:1a
14	5.193192947	192.168.1.100	99.83.172.119	MQTT	60	Disconnect Req
15	5.193699389	192.168.1.100	99.83.172.119	TCP	60	59880 → 1883 [FIN, ACK] Seq=123 Ack=5 Win=1456 Len=0
16	5.338709513	99.83.172.119	192.168.1.100	TCP	54	1883 → 59880 [ACK] Seq=5 Ack=123 Win=65535 Len=0
17	5.338714704	99.83.172.119	192.168.1.100	TCP	54	1883 → 59880 [FIN, ACK] Seq=5 Ack=124 Win=65535 Len=0
18	5.339267333	192.168.1.100	99.83.172.119	TCP	60	59880 → 1883 [ACK] Seq=124 Ack=6 Win=1455 Len=0

After many tests I realized with help from my friend Marcelo Barros that the issue was because the mqttc didn’t wait the MQTT ACK before sending data and it confuse the server that refuses to accept further data.

I submitted a fix to let mqttc on NuttX to wait for the MQTT ACK: https://github.com/apache/nuttx-apps/pull/1748

Compiling same NuttX libs to use on Linux

I was facing an issue with cJSON and MQTT-C on NuttX and decided to do a test: copy these libs source code from NuttX and then compile them on Linux and link my application with them (my app is just the modified mqttc example, so I will copy it too).

So I entered into nuttxspace/ directory and copied them to my home dir:

$ cp -a apps/netutils/cjson ~/
$ cp -a apps/netutils/mqttc/MQTT-C ~/
$ cp -a apps/examples/mqttc ~/

The cJSON was easy to compile:

$ cd ~/cjson/cJSON-1.7.12/
$ make all
$ sudo make install
$ sudo ldconfig

For MQTT-C I don’t need to compile, I just copied the files:

$ cd ~/MQTT-C
$ cp src/mqtt* ~/mqttc/
$ sudo cp include/mqtt* /usr/local/include/

Now I just entered inside ~/mqttc and compiled all the files:

$ cd ~/mqttc/

$ ls
Make.defs  Make.dep  Makefile  mqtt.c  mqttc_pub.c  mqtt_pal.c  README.md
$ gcc -c mqtt.c -o mqtt.o
$ gcc -c mqtt_pal.c -o mqtt_pal.o
$ gcc -c mqttc_pub.c -o mqttc_pub.o -DFAR= -DOK=0 -DERROR=-1 -DCONFIG_EXAMPLES_MQTTC_TXSIZE=256 -DCONFIG_EXAMPLES_MQTTC_RXSIZE=256

Finally just link all .o files:

$ gcc mqttc_pub.o mqtt.o mqtt_pal.o -o mqttc_pub -lcjson -lpthread

Lets run the executable:

$ ./mqttc_pub -h mqtt.tago.io -p 1883 -n 3
Connecting to mqtt.tago.io:1883...
Success: Connected to broker!
{
	"variable":	"temperature",
	"unit":	"C",
	"value":	10
}
Success: Published to broker!
{
	"variable":	"temperature",
	"unit":	"C",
	"value":	10
}
Success: Published to broker!
{
	"variable":	"temperature",
	"unit":	"C",
	"value":	10
}
Success: Published to broker!

Disconnecting from mqtt.tago.io

NuttX is very similar to Linux, same libs, same errors:

Update: the issue was in tago.io system: it doesn’t accept the payload string ending with ‘\0’ see:

{
    "topic": "tago/data/post",
    "payload": "[{\"variable\":\"temperature\",\"value\":32}]\u0000",
    "qos": 0,
    "isHex": false,
    "bucket": "635bb8b9e68e400011343782",
    "messageId": 0
}

A workaround to fix the issue was removing that “+ 1” after the strlen() here:

  mqtterr = mqtt_publish(&mqtt_cfg.client, mqtt_cfg.topic,
                         mqtt_cfg.msg, strlen(mqtt_cfg.msg) + 1,
                         mqtt_cfg.qos);

I contacted TagoIO and they will fix it

Update: fixed the mqttc_pub.c compilation with suggestion from Petro Karashchenko

Getting deep in the rabbit hole of Andes NDS32

As you saw in my previous post I figure-out that my audio mixer was using a MVSILICON BP1048B2 microcontroller.

This chip uses the Andes NDS32 architecture internally. More specifically it is a NDS32 V3S MCU.

After posting about it on Twitter my friend @atc1441 find out the repository and discovered that is using some kind of SWD for programming:

Then searching in the Internet I found that there are other chinese chips using this same NDS32 architecture on MCUs, for example the powerful offline audio recognition chip Unisound US516P6:
https://www.cnx-software.com/2021/05/14/us516p6-risc-microcontroller-powers-offline-voice-assistant-modules/

I figured out what chip my audio mixer F998 is using

It is a strange behavior, but normally chinese companies erase the chip’s name used on their products:

Trying to protect your product using obfuscation is not a good idea, soon or later someone will figure-out it. Actually I figured the chip used on this product in less than 5 minutes (AFAIK I was the first one to figure out it).

They are using the MVSilicon BP1048B2. I also found the datasheet (brief-sheet), but didn’t found the SDK for it and how to program it.

This chip seems mostly used on Audio Sound Bars and other audio bluetooth products.

This chip is very powerful, seems a good candidate to run NuttX RTOS, see:

So, if you get more information about this chip, please let me know!

Update: Aaron Christophel (aka atc1441) found the SDK for this chip on github:
https://github.com/leadercxn/bp1048_sdk_v0.1.12

How to listen your microphone output in the computer speaker

So you also got an audio mixer F998 and want to test it on your Linux computer!?
The easier way to have fun with it is connecting its Earphone output to your computer audio microphone input using the P2 cable that come together with your mixer.

Then install this package:

$ sudo apt-get install pavucontrol 

And run this command:

$ pactl load-module module-loopback latency_msec=1

If you want to disable it and return to normal (no microfone sound on speakers) run

$ pactl unload-module $(pactl list short modules | awk '$2 =="module-loopback" { print $1 }' - )

Source: https://askubuntu.com/questions/123798/how-to-hear-my-voice-in-speakers-with-a-mic

OpenOCD ESP32 IR capture error; saw 0x1f not 0x01

If you see this error while trying to use OpenOCD with JTAG on ESP32:

$ sudo esp32-openocd -c "set ESP_RTOS none" -f board/esp32-wrover-kit-3.3v.cfg
Open On-Chip Debugger  v0.10.0-esp32-20210401-48-g041b08f6-dirty (2022-10-15-18:05)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
none
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : ftdi: if you experience problems at higher adapter clocks, try the command "ftdi_tdo_sample_edge falling"
Info : clock speed 20000 kHz
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: esp32.cpu0: IR capture error; saw 0x1f not 0x01
Warn : Bypassing JTAG setup events due to errors
Info : Listening on port 3333 for gdb connections
Info : accepting 'gdb' connection on tcp/3333
Error: Target not examined yet
Error executing event gdb-attach on target esp32.cpu0:

And after including the suggested “ftdi_tdo_sample_edge falling”

$ sudo esp32-openocd -c "set ESP_RTOS none" -f board/esp32-wrover-kit-3.3v.cfg
Open On-Chip Debugger  v0.10.0-esp32-20210401-48-g041b08f6-dirty (2022-10-15-18:05)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
none
ftdi samples TDO on falling edge of TCK

Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 20000 kHz
Error: JTAG scan chain interrogation failed: all ones
Error: Check JTAG interface, timings, target power, etc.
Error: Trying to use configured scan chain anyway...
Error: esp32.cpu0: IR capture error; saw 0x1f not 0x01
Warn : Bypassing JTAG setup events due to errors
Info : Listening on port 3333 for gdb connections
Info : accepting 'gdb' connection on tcp/3333
Error: Target not examined yet
Error executing event gdb-attach on target esp32.cpu0:

This error is easy to fix: you are connecting something external to GPIO pins 12-15 or you are enabling these pins in your code.

Source: https://www.esp32.com/viewtopic.php?t=14069

Types of measuring for quadrature encoders

When working with quadrature encoder hardware you can face three scenarios or should say ways to read the quadrature encoders pulses: X1, X2, X4.

In X1 mode only the rising pulse is considered. For example if channel A rises while channel B is in low level, then it consider positive counting (clockwise). If channel A rises while channel B is in high level, then it is consider negative counting (counter-clockwise).

For X2 mode the rising and falling of channel A is considered. In this mode the counting is doubled compared to X1.

Finally in X4 mode the rising and falling of channels A and B are considered. In this mode the counting is quadruplicated in relation to X1 mode.

Source1: https://www.dynapar.com/technology/encoder_basics/quadrature_encoder/
Source2: https://www.motioncontroltips.com/faq-what-do-x1-x2-and-x4-position-encoding-mean-for-incremental-encoders/

Using ESP32 PCNT as QE: https://www.esp32.com/viewtopic.php?t=4983#p21497