Go Down

Topic: Auto reset and upload sketch seamlessly with Bluetooth Mate (Read 10259 times) previous topic - next topic

ma_hty

Oct 20, 2012, 03:50 am Last Edit: Oct 21, 2012, 12:26 am by ma_hty Reason: 1
Programming Arduino via bluetooth should be a natural application to any bluetooth serial module.  As least, I believe so.  Therefore, I brought a couple of cheapest bluetooth serial modules I can find along with my Arduino Kit  (http://www.ebay.com/itm/Wireless-Bluetooth-Module-Slave-4Pin-Serial-Port-DuPont-Cable-For-Arduino-/160902163152?pt=US_USB_Bluetooth_Adapters_Dongles&hash=item2576842ad0).  However, a natural application like this turns out to be a non readily available one.  For some reasons, people is kind of accepting it, probably because there are some expensive solutions in the market (so cheap one shouldn't work).

Anyway, to program a Arduino through bluetooth, we need to solve two problems. The first one is auto resetting the Arduino board, and the second one is to synchronize the resetting moment to the uploading moment. http://ame2.asu.edu/staff/kidane/ArdWilessBtProg.pdf solved the first one nicely, but not the second one.  To use it, we need to send a char to the Arduino board though serial console to trigger the reset, while hoping that the uploading moment will hit the tiny resetting time frame (e.g. 2 seconds in case of Arduino UNO).  (... I can't even come close to make them meet ...)

Fortunately, both short comings can be solved easily by modifying your the Arduino code a little bit.  As a matter of fact, the Arduino IDE is sending two chars {0x30,0x20} to the Arduino board, and expecting two chars reply {0x14,0x10} to synchronize the upload process.  We just need to mimic this behavior and resetting the board promptly, then we have a perfect syn.  The following is the actual working Arduino source code for this.  (The downside is you have to somehow escape '0' from your input stream, which may or may not be a problem.)

//////////////////////////////////////////////////////
//
int uploadpin=8;

void setup()
{
 Serial.begin(115200);  // baudrate 115200 corresponds Arduino UNO,
                                   // it can be different for different boards
 pinMode(uploadpin,OUTPUT);
}

void loop()
{

 // your codes here...
 
 /////////////////////////////////////////
 // Upload checking
 if( Serial.peek()=='0' )
 {
   for( int i=0; i<100; i++ )  // repeat the check for a short peroid
   {
     if( Serial.read()=='0' && Serial.read()==' ' )
     {
       Serial.write(0x14);  // reply two char to avrdude.exe
       Serial.write(0x10);  //  for synchronization
       digitalWrite(uploadpin,HIGH);  // turn on the relay to ground the reset pin
     }
     delay(10);  // cannot repeat too fast here
   }
 }
 /////////////////////////////////////////
}
//
//////////////////////////////////////////////////////

With the above source code (and the solution described in the .pdf file), you should theoretically be able to upload sketch by clicking the upload button in the Arduino IDE.  However, for some reasons (probably came from rxtxSerial.dll or the standard bluetooth driver), an error "avrdude: ser_open(): can't open device "\\.\COM16": Element not found."  may happen.  What's this error actually saying is your bluetooth serial connection fail to reopen immediately after close.  (Don't panic, it's okay).   You can upload your sketch via console by calling avrdude.exe directly.  Turn on the upload verbose by checking the FILE>Preferences>Show verbose output during>upload checkbox, click the upload button once, then you will find the avrdude command in the Arduino IDE reporting window. Here is an example
"C:\Arduino\arduino-1.0.1\hardware/tools/avr/bin/avrdude -CC:\Arduino\arduino-1.0.1\hardware/tools/avr/etc/av
rdude.conf -v -v -v -v -patmega328p -carduino -P\\.\COM16 -b115200 -D -V -Uflash:w:C:\Users\Gary\AppData\Local\Temp\build4211658377325489507.tmp\code1.cpp.hex:i"

This command will stay exactly the same before you close the Arduino IDE window.  So, you just need to copy it once, paste it in a console window, compile your Arduino source code, and keep reusing with same command for upload as long as the Arduino IDE window stay open.

Alternatively, stop the Arduino IDE from flushing the serial connection before uploading will also solve the problem.  You can do that by editing your board setting in C:\Arduino\arduino-1.0.1\hardware\arduino\boards.txt.  For Arduino UNO, add "uno.upload.disable_flushing=true".  Its a little bit risky to edit that file, do it unless you know what you are doing.  ( Flushing the serial connection before uploading doesn't seems do anything beside locking up the serial connection. Why is Arduino IED doing in the first place?)

<<<<<PLEASE PAY ATTENTION HERE>>>>>


The solution described in the pdf, http://ame2.asu.edu/staff/kidane/ArdWilessBtProg.pdf , requires three simple, but very error prone steps.  I simplified them for you.  Just follow to the letter, don't ask.

1) There is a reset pin in Arduino UNO.  You don't have to solder the transistor.  Just connect it to reset pin via jump wire, it works fine.

2) Replace C:\Arduino\arduino-1.0.1\rxtxSerial.dll with http://servicios.ried.cl/arduino/temp/rxtxSerial-2.2_fixed_2009-03-17.rar
(For the details, http://arduino.cc/forum/index.php/topic,46977.0.html.)

3) Update AT command of Bluetooth Mate.  
The buadrate for upload of different board can be different.  You can check C:\Arduino\arduino-1.0.1\hardware\arduino\boards.txt for details.

Unlike USB serial, Bluetooth Mate can only operate at a particular buadrate.  To change the bluetooth mate buadrate, you can connect it to the computer with a USB-TTL cable, use a terminal software to send the AT command.  The AT command is in a format  like AT+BUAD1 or AT+BUAD2 or AT+BUAD3...  The number 1, 2, 3 is the indices to a list of specific buadrates, e.g. 8->115200. (See http://thingylab.com/wiki/hc06_linvor_1.5_at_command_set for details).

If you don't have a USB-TTL cable, you can simple use your Arduino board as one.  Connect your bluetooth mate to your board like this





VCC -> 5V
TX -> TX(pin1)
RX -> RX(pin0)
GND -> GND
, use a jump wire connect reset pin to ground, and connect the arduino board to computer with a usb cable.
At this point, you can send AT command via the Arduino IDE serial window.  For testing, you can send "AT", it should respond "OK". ( For details, see http://arduino.cc/forum/index.php/topic,18243.0.html.)

(Tired... I should simply make a video instead of writing...)



card5

Hi ma_hty

Thank you for this extremeley helpful information!

Morph

Hi ma_hty,

As a newbie to Arduino, your info gave me the final pieces of the jigsaw puzzle that I needed to allow program uploading via blue tooth. Many thanks.

Using the direct command to avrdude via the Windows command prompt was the final bit I needed.

I found a simple solution to "escaping '0' from the input stream" is to only enable the upload checking routine for a period of 60 seconds from start up - provides plenty of time for program upload using avrdude command - just have to have an On/Off switch for power to the Arduino.

I did try adding "uno.upload.disable_flushing=true" to the board file but that seemed to interfere with library references for some reason.
Morph

oangelo

Hi,

I am trying this solution, but I am a Linux user and I have made some changes, I am using this solution to restart the Arduino:
http://www.instructables.com/id/two-ways-to-reset-arduino-in-software/

So, I connected the pin 12 to the RESET pin and used this code:

#define RESETPIN 12

void setup()
{
  digitalWrite(RESETPIN, HIGH);
  Serial.begin(57600); //The specific baud rate of my devices
  pinMode(RESETPIN, OUTPUT);
}

void WatchUpload() {
  if ( Serial.peek() == '0')
  {
    for ( int i = 0; i < 100; i++ ) // repeat the check for a short peroid
    {
      if ( Serial.read() == '0' && Serial.read() == ' ' )
      {
        Serial.write(0x14);  // reply two char to avrdude.exe
        Serial.write(0x10);  //  for synchronization
        digitalWrite(RESETPIN, LOW);  // turn on the relay to ground the reset pin
      }
      delay(10);  // cannot repeat too fast here
    }
  }
}


void loop()
{
  delay(10);
  Serial.println("Helow World");
  WatchUpload();
}

Some times the code works sometimes it doesn't. Anybody have any clue?
Thanks.

PaulS

Quote
Anybody have any clue?
Yes. Your way of reading serial data is complete rubbish.
The art of getting good answers lies in asking good questions.

oangelo

Great, how do I correct it? Look, I am flying blind here, I was just trying the solution proposed by ma_hty, see the first post.

PaulS

The art of getting good answers lies in asking good questions.

oangelo

Actually, my problem is not how to use the serial... The problem is everything else!
To be able to send sketches to Arduino using bluetooth is well beyond knowing how to manage the Serial, you have to reset the board and synchronize the resetting moment to the uploading moment. Have you read the first post? Have you tried it?

PaulS

Quote
To be able to send sketches to Arduino using bluetooth is well beyond knowing how to manage the Serial,
Agreed. But, you don't even know how to do that, so anything beyond that hasn't a hope in hell of working.
The art of getting good answers lies in asking good questions.

oangelo

I am not an expert, but my code is based on the code of the first post. That code has a problem too? Can you tell me what the problem is? I couldn't figure it out by myself...

PaulS

Quote
That code has a problem too?
Yes.

Quote
Can you tell me what the problem is?
There is no checking to see that there is serial data to read.
There is nothing to deal with Serial.read() not being able to read any serial data.
There is no assurance that two reads per iteration of the loop will be performed, even if serial data arrives as fast as the Arduino can read it (which does not happen).
The art of getting good answers lies in asking good questions.

oangelo

You are right, the code is strange...
What do you think about the following code?
I've made some comments to make my ideas clear.
Now it works more, half of the times, but not always.
You still can spot any problems?

#define RESETPIN 12

void setup()
{
  digitalWrite(RESETPIN, HIGH);
  Serial.begin(57600); //The specific baud rate of my devices
  pinMode(RESETPIN, OUTPUT);
  pinMode(13, OUTPUT);
}

void WatchUpload() {
  //From what I understand of C++ the second condition will only be evaluated if the first is true.
  if ( Serial.available() > 1 && Serial.peek() == '0')
  {
    //If we have the restart condition, we can read data from the buffer
    if ( Serial.read() == '0' && Serial.read() == ' ' )
    {
      digitalWrite(13, HIGH); //Turn on the led, so we can see if the board resets
      Serial.write(0x14);  // reply two char to avrdude
      Serial.write(0x10);  //  for synchronization
      Serial.flush(); //wait the transmission
      digitalWrite(RESETPIN, LOW);  // RESET (turn on the relay to ground the reset pin)
      digitalWrite(13, HIGH); //if reset happens this should never be executed
    }
  }
}


void loop()
{
  delay(10);
  Serial.println("Hello world");
  WatchUpload();
}

oangelo

Another odd thing is that it seems that HC-05 works better than HC-06.
Using HC-05 I can record the sketches half of the times, with the last code I sent, when I use HC-06 it is very difficult, almost always I receive this error:
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x6c
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x20
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x48
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x65
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x6c
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x6c
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x6f
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x20
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x77
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x6f

The code does resets the board right, the problem is after that, the synchronization, I think.
Any suggestions?

Go Up