Upload Arduino sketch via AI2 and Bluetooth

Hello All,
I'm working on a solution where I can update the code on an Arduino Nano via a cheap JDY-31 Bluetooth dongle.

  • The Arduino RX0 TX1 is connected to the JDY-31's TX and RX, using voltage divider for RX so the 5V will not harm the HC06 RX that is 3.3V capable
  • The communication works smooth using my phone or my PC
  • Since the boot loader on the Arduino use 115200 baudrate, I set up the JDY-31 to use that baud rate (by AT+BAUD8\r\n command)
  • I can upload sketch via Bluetooth from my PC. I paired the PC's Bluetooth device with JDY-31 and COM11 appeared as an option for serial communication. I selected it in Arduino IDE and if I upload, I have to manually reset the Arduino board and uploading the sketch from Arduino IDE works perfectly - if I reset the microcontroller using good timing, then it works 100% correctly.

I thought I might be able to replicate the protocol that the avrdude.exe uses in my PC with an AI2 app. I know it uses the STK500v1 protocol. I want to create a tutorial for everyone if I succeed because I haven't found a complete tutorial. Maybe it's not a coincidence, considering my findings.

I created an app that is very basic:

  • It downloads the binary sketch in a text format, connects to the dongle
  • It initiates the update, waiting for byte 0 from Bluetooth client
  • When I reset the Arduino board it sends byte "0" and the app sends back "0x30 0x20" (STK_GET_SYNC CRC_EOP) to get sync from the remote end, waiting for "0x14 0x10" etc.

The exact details of the protocol commands I derived by using the avrdude.exe over the air and at the same time I captured the communication with another Nano board. So at the end, it should've been a matter of time to implement the full protocol by simply having a chat between the phone and Arduino Nano (and of course JDY-31 in between).

The thing is, it works until one point and it's not stable. Some times it gets SYNC but fails the next command. Some times it goes through SYNC, query parameters, set device, set device extended parameters and then fails. The whole thing is unstable and unpredictable. I don't know what could I do better? I can upload from my PC, using the same dongle and Nano board 100% correctly and it fails from the phone.

I can't share the full app due to lack of visibility so I'll try to focus on explaining how it works. Maybe the problem is in the way I use the BluetoothClient component, or using Clock to schedule the communication?

  • When "but_update" is clicked, I start the timer so "when clock.Timer()" will be triggered
  • There is a helper function "wait_optiboot_1s" that receives all bytes from Bluetooth and looks for a certain value (usually 0x10 = STK_OK). If I get the correct answer, I'll go to the next phase (increase the global variable "phase") and send the next command, wait again for the correct answer etc.

Is this a correct approach? Why it works from my PC, using avrdude.exe and lost sync when I recreate the same conversation with AI2? Any suggestions, please?

Thank you!


2

Hello Atomgep

A very brave project!

"Bytes Available To Receive" is just a flag. You need to use math Blocks for a specific number of bytes, or -1 for all available bytes.
Math -1

1 Like

You may have a look at my extension com.SerialOTG.aix. SerialOTG_BT_WIFI.aia show you how to use it for upload to an Arduino using the SDK500 protocol. Arduino_BT.pdf show you how to do a automatic reset before upload.

(The extension uses an updated version of the Physicaloid library and communicates using Serial, BT or WIFI in the same way )

See: https://github.com/rkl099/Appinventor-SerialOTG

1 Like

Thank you, I'll rework that part. Actually, I suspected there is something wrong, because the Nano sends only one byte "0" but my procedure received much more zeroes than expected.

UPDATE: I tried to use as you suggested. However I didn't get what I expected. When I use -1 it only gets one byte (0) then gives back the control to when Clock.Timer(). This is OK however the Clock.Timer() is triggered in every 50ms (well, as I've read it's not written in stone, it's just a request to Android OS but the OS can override if there are other more important apps running) and the BT buffer contains lots of zero bytes (I can't tell why, this is how the Nano works, it sends that much zero bytes) and the Clock.Timer() is too slow to read the buffer out one by one and ultimately times out.

I suspect the default delimiter byte for the BluetoothClient is the zero byte, that's why it reads only one byte because it immediately fulfills the condition to "read until delimiter byte".

On the contrary, if I use Bluetootclient1.BytesAvailableToReceive() it gets those much zero bytes at once in a buffer. I don't know why exactly? The help says "this is an estimated number of bytes that can be received without blocking" and it seems to work like that. I've created another function to flush this buffer and get rid of the zeroes (however it will also receives the non-zeroes that are useful in the later phases when I expect "0x14 0x10" and I don't want to loose them.

So I changed the wait_optiboot() function again and I set the delimiter byte to that one I am looking for at the moment. Unfortunately this is not good either, because if the expected byte did not arrive, it hangs up the app, it waits forever. (I thought the when Clock.Timer() will be executed and in its next cycle I can check for timeout but it does not work in the current form of course because at the first line I re-call wait_optiboot() again and again....).

Please see how it looks now. It's not what I imagined but we are on the way...



Thank you much, I'll definitely take a look! Sounds cool!

UPDATE: I've checked the .aia with the Extension. I really appreciate the effort you put into this, it's really a complex thing!

I could connect to my dongle via BT and I tried an upload. I faced with two issues:

  1. The Extension can upload only from a file from the phone. I didn't plan to ask for a file permission because I download from the Internet and users usually don't really favour giving file permission anyway. But it's not that big problem if it'd work.
  2. When I clicked on the upload button, it started uploading but then nothing happened on the app side, the error codes turned to zero on the screen and it seemed hanging. I captured the communication at the Nano side, it seems it can't go further than

30,20,30,20,30,20,41,81,20,41,82,20,42,86,0,0,1,1,1,1,3,FF,FF,FF,FF,0,80,4,0,0,0,80,0,20,

(I only captured RX so you can't see the replies from Nano. These are of course hex numbers.)

So, upload failed. Multiple times. I don't know why because I totally lack any possibility to investigate the root cause. Maybe the issue is with my phone? It's a Samsung S10e, it's really not a low-end device so I think it can't be the issue.

Thank you, keep up the good work, if you have suggestion how to debug I'll try.

You can make a List of the commands and send via a for loop. In the example below, the time interval per send is variable, you may not need that.

BT_Send_Commands.aia (9.5 KB)

The image needs to be downloaded to be readable.

.... you can measure how well things are going by how much of your hair has gone grey in just 3 days!

1 Like

Thank you for your .aia, it was very educational, especially I like the connection part. Actually, the variable interval is not that important, but I also like the way you added the commands into the List. I have to use bytes 0-255 and AI2 uses UTF8 and I couldn't figure yet how to create texts with these exotic values > 127, so I decided to create list of number representations. It went well so far, I only kept the "phase1" part because it's a bit special as I'm waiting for the reset of the Nano at the remote end.
I'll put everything together and will upload the code as .aia.

Haha Man, I feel too much hairs I'm going to loose with this... :slight_smile:

Cheers,

Yeah, that's not right!

Hello Guys,

after a little while and after having some tranquilizers I could come up with the first working version. I have not implemented the verification yet (but it is necessary, I'm afraid) but the upload works - well, more or less. With smaller .hex files like Blink it works seamlessly. The binary is getting bigger, the chances for having some issue (either timeout or maybe some bits are altered in the BT communication) is getting bigger, too. I'm not really sure how to tackle this issue other than verify the uploaded sketch and report if something was wrong. Also, maybe my code is not perfect somewhere, I don't know - that's why I wanted to publish it. Another thing I was thinking of is a better circuit that gets less noise from the environment.

How it works:

  • You have to have the .hex version of your sketch. (If you compile it in the Arduino IDE, it tells where you can find the binary at your computer. Use the .hex file and not the .bin; the .hex is a text file really that I could download and process easily.)
  • When you click on the download button, it gets the URL from the field in the screen. Then it interpret the intel .hex file format (only if it's 8 bit, I don't handle memory addressing > 64kbyte), break it into 128 byte pages (this is the biggest memory size you can write at once), then put it to a List
  • Connecting to the BT dongle should not be a problem
  • The "upload" button first wait for the restart of the Nano (in fact, it waits for zeroes in the BT communication), then it starts doing its thing. It gets a sync then send some trivial commands to see if the other end is really an Atmel328p with a bootloader. Then it loads the memory addresses and write the stuff from the global variable (List called "file").
  • At the end, it closes prog mode.

I used an excellent article to implement the above protocol.

I hope someone will try out and maybe improve it. :slight_smile:

I hope you're going to enjoy it.
Cheers!
letolto.aia (21.4 KB)

Itching to try it out but my Arduino is out of bounds as the house is currently a building site. The linked article by Nick Gammon is very interesting.

Next stop Nano 33 BLE?

This sequence seems to be correct: Sync, Sync, Sync, STK_GET_PARAMETER, STK_SET_DEVICE. These are part of the STK500 protocol but are normally not used when programming a device with the bootloader. Look at this reference : Bluetooth SPP support · Issue #6 · rkl099/Appinventor-SerialOTG · GitHub that indicate that optiboot may not be compatible with this implementation, which is based on the original Physicaloid library.

1 Like