Category: Dicas NuttX

Sheding some (infrared) light on MLX90614

After implementing the MLX90614 driver for NuttX I noticed that although the write command to change the device I2C address in the EEPROM was reporting success, after the power cycle the new address was not working. Worst: even the previous address was not working.

Basically the device appears damaged and didn’t respond to any I2C command.

Then doing my research I discovered a Melexis document about SMBus communication:

https://www.pololu.com/file/0J171/MLX90614_SMBus.pdf

In this document I noticed they are using the address 0x00 instead of the default 0x5a address. After modifying the driver to use the 0x00 address the device accepted the new command.

There are many discussing about this subject on Arduino and similar forum:

https://chrisramsay.co.uk/posts/2014/09/arduino-and-multiple-mlx90614-sensors/
http://forum.arduino.cc/index.php?topic=54170.msg539601#msg539601
https://forum.mikroe.com/viewtopic.php?f=178&t=67842
http://wiki.wiring.co/wiki/Connecting_Infrared_Thermometer_MLX90614_to_Wiring

Note that someone discovered that using a brute force CRC approach eventually will work and everybody decided to copy it. Too bad guys!

The MLX90614 uses CRC8-CCITT standard to check if data are correct, so any CRC8-CCITT implementation will work, for example this one: https://3dbrew.org/wiki/CRC-8-CCITT

Now on NuttX you can call the mlx90614 example application to change the device’s I2C address this way: (changing from default 0x5a to 0x3a)

nsh> mlx90614 0x3a
Address 0x3a stored on your device!
Please do a power cycle and update the I2C board address!
nsh>

Checking the CRC-8 PEC byte of MLX90614

I am creating a NuttX device driver for Melexis MLX90614 and it is a nice adventure.

First I downloaded the adafruit lib and tested it on Arduino Uno just to confirm the sensor was working, but I didn’t look the source code because I always prefer to read the datasheet and implement the driver from scratch.

All things fine, the mlxtest example worked correctly and I got the ambient temperature and the object temperature printed correctly.

Then I created the driver and decided to test it on STM32F103, but discovered that I2C_TRANSFER() for STM32F103 is broken. No problem, let to test it on STM32F4Discovery board:

nsh> dd if=/dev/thermo0 of=/dev/null bs=2 count=1
mlx90614_read_word: value[0]: 0xDF | value[1]: 0x3A | value[2]: 0xCF | ret: 0

Let see in the logic analyzer to confirm:

Very good! But how to check if CRC-8 PEC field (third received byte: 0xCF) is correct?

I found this nice online CRC calculator:

http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

But putting all values as suggested in the datasheet didn’t work:

0x5A 0x06 0x5A 0xDF 0x3A
Result CRC value: 0x2F

Then just web searching for: MLX90614 PEC CRC-8 example

Returned me this thread:

https://stackoverflow.com/questions/20554869/implementing-crc8-on-arduino-to-write-to-mlx90614

The “thb” guy saved me:

“I haven’t checked your CRC implementation but there is a mistake in the MLX datasheet or at least it’s badly written. You have to include all the I2C frame’s data for the PEC’s calculation not just the replied data. For a read word command you have to include [SA_W, Command, SA_R, LSB, MSB] and for a write word command [SA_W, Command, LSB, MSB]. So, for their first example the calculation must be made on [ 0xB4, 0x07, 0xB5, 0xD2, 0x3A ] and not just on [ 0xD2, 0x3A ] and this way you get the expected 0x30.”

What this guy is saying is: we need to include all the bits of the Slave Address, the address needs to be seen as 8-bit including the the less significant bit Write or Read. So I2C Write at address 0x5A is seen as 0xB4 and I2C Read is seen as 0xB5 (pay attention at bits over the “5A” in the logic analyzer image above).

So, let to try his idea:

0xB4 0x06 0xB5 0xDF 0x3A
Result CRC value: 0xCF

Bingo!

Running NuttX on LPCXpresso54628 OM13098

Today I tested NuttX running the LVGL demo on LPCXpresso54628.

Here you can find the steps needed to get it working.

First compile the firmware to create the nuttx.bin:

$ ./tools/configure.sh lpcxpresso-lpc54628/lvgl
$ make menuconfig
$ make

Now you can flash the firmware using JLinkExe on Linux.

You can use the LPC54608J512 even to flash the LPC54628:

$ sudo JLinkExe -if SWD -device LPC54608J512
SEGGER J-Link Commander V6.32h (Compiled Jul  5 2018 18:15:02)
DLL version V6.32h, compiled Jul  5 2018 18:14:58

Connecting to J-Link via USB...O.K.
Firmware: J-Link ARM V8 compiled Nov 28 2014 13:44:46
Hardware version: V8.00
S/N: 268006167
License(s): FlashBP, GDB
OEM: SEGGER-EDU
VTref=3.293V

Type "connect" to establish a target connection, '?' for help

Run “connect” command:

J-Link> connect
Specify target interface speed [kHz]. : 4000 kHz
Speed>
Device "LPC54608J512" selected.
Connecting to target via SWD
Found SW-DP with ID 0x2BA01477
Found SW-DP with ID 0x2BA01477
Scanning AP map to find all available APs
AP[1]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x24770011)
Iterating through AP map to find AHB-AP to use
AP[0]: Core found
AP[0]: AHB-AP ROM base: 0xE00FF000
CPUID register: 0x410FC241. Implementer code: 0x41 (ARM)
Found Cortex-M4 r0p1, Little endian.
FPUnit: 6 code (BP) slots and 2 literal slots
CoreSight components:
ROMTbl[0] @ E00FF000
ROMTbl[0][0]: E000E000, CID: B105E00D, PID: 000BB00C SCS-M7
ROMTbl[0][1]: E0001000, CID: B105E00D, PID: 003BB002 DWT
ROMTbl[0][2]: E0002000, CID: B105E00D, PID: 002BB003 FPB
ROMTbl[0][3]: E0000000, CID: B105E00D, PID: 003BB001 ITM
ROMTbl[0][4]: E0040000, CID: B105900D, PID: 000BB9A1 TPIU
ROMTbl[0][5]: E0041000, CID: B105900D, PID: 000BB925 ETM
Cortex-M4 identified.

Finally flash nuttx.bin using the loadbin command:

J-Link>loadbin ./nuttx.bin 0
Halting CPU for downloading file.
Downloading file [./nuttx.bin]...
Comparing flash   [100%] Done.
Erasing flash     [100%] Done.
Programming flash [100%] Done.
Verifying flash   [100%] Done.
J-Link: Flash download: Bank 0 @ 0x00000000: 1 range affected (360448 bytes)
J-Link: Flash download: Total time needed: 3.314s (Prepare: 0.058s, Compare: 0.009s, Erase: 0.991s, Program: 2.245s, Verify: 0.005s, Restore: 0.003s)
O.K.
J-Link> exit

Reset the board and you should see the touchscreen calibration screen.

And then:

Using FAT32 long file names on NuttX

NuttX supports FAT32 with long file names, but there is some details that you need to know to get it working. I will share here the issues that I was facing and how I fixed it.

The original FAT uses 8.3 (8 chars for name and 3 chars for extension), but it can supports files with up to 255 characters (including the extension).

To use it we need to enable long file name support in the menuconfig:

 File Systems  --->
     [*] FAT file system
     [*]   FAT upper/lower names
     [*]   FAT long file names             -------->  (CONFIG_FAT_LFN=y)
     (255)   FAT maximum file name size    -------->  (CONFIG_FAT_MAXFNAME=255)

Initially I will mount an empty SDCard to do my tests:

NuttShell (NSH)

nsh> mount -t vfat /dev/mmcsd0 /mnt

nsh> ls /mnt
/mnt:

nsh>

Let’s to create a small 8.3 file that will be renamed:

nsh> echo "Small file" > /mnt/tinyfile.txt
nsh> ls -l /mnt/tinyfile.txt
 -rw-rw-rw-      12 /mnt/tinyfile.txt
nsh>

Now I will try to rename it to a file with a long name:

nsh> mv /mnt/tinyfile.txt /mnt/this_is_a_file_with_a_long_name_jnsh>

Strange, while I was typing “this_is_a_file_with_a_long_name_just_for_test.txt” the typing was interrupted and the nsh> appeared.

Let see if the file was renamed:

nsh> ls /mnt
/mnt:
 this_is_a_file_with_a_long_name_

Then I remembered that the max line size of NSH was just 60 (CONFIG_NSH_LINELEN=60), I will increase it to 300 characters:

Application Configuration  --->
    NSH Library  --->
          Command Line Configuration  --->
              (300) Max command line length    -------->  (CONFIG_NSH_LINELEN=300)

I will create a tinyfile.txt again and try to rename it:

nsh> mv /mnt/tinyfile.txt /mnt/this_is_a_file_with_a_long_name_just_for_test.txt
nsh> 

Right, now the nsh prompt accept the enter the name, but let see if the file was created correctly:

nsh> ls /mnt
/mnt:
 this_is_a_file_with_a_long_name_
 this_is_a_file_with_a_long_name_

Whoa, it created two files with same name? How it is possible? Don’t worry, these files are different. Opening the SDCard in the Linux I can see:

this_is_a_file_with_a_long_name_j
this_is_a_file_with_a_long_name_just_for_test.txt

So, the LS command is showing only 32 characters. After some investigation I discovered that CONFIG_NAME_MAX=32 was the issue. Let to increase it to 255:

RTOS Features  --->
    Files and I/O  --->
        (255) Maximum size of a file name    -------->  (CONFIG_NAME_MAX=255)

Now I can see the files:

nsh> ls /mnt
/mnt:
 this_is_a_file_with_a_long_name_j
 this_is_a_file_with_a_long_name_just_for_test.txt

My next step is to create a file with 255 characters, like this:

this_file_will_have_a_big_filename_to_verify_how_to_work_with_files_with_long_names_our_test_need_to_have_the_max_filename_size_supported_by_fat32_that_means_it_could_have_up_to_255_characters_including_the_extension_in_the_filename_so_here_we_arrived.txt

nsh> echo "Test" > /mnt/this_file_will_have_a_big_filename_to_verify_how_to_work_with_files_with_long_names_our_test_need_to_have_the_max_filename_size_supported_by_fat32_that_means_it_could_have_up_to_255_characters_including_the_extension_in_the_filename_so_here_we_arrived.txt
nsh> ls /mnt
/mnt:
 this_file_will_have_a_big_filename_to_verify_how_to_work_with_files_with_long_names_our_test_need_to_have_the_max_filename_size_supported_by_fat32_that_means_it_could_have_up_to_255_characters_including_the_extension_in_the_filename_so_here_we_arrived.txt
nsh> 

Very nice! It worked correctly.

As you can see NuttX is similar to Linux kernel, many features depends on other features’ configuration. They are inter-dependent.

NuttX now supports LVGL

If you follow my blog you know my previous post was about LVGL. Today I want to announce that LVGL was ported to run on NuttX.

Gábor Kiss-Vámosi the author of LVGL ported it to run on top of NuttX, using NuttX’s framebuffer support.

It is in early stage, it needs more integration to support touchscreen, mouse, keyboard and maybe even audio subsystem integration, but it was the first step!

A picture is worth a thousand words: