having got the bluesmirf working, now time to start sending and receiving some proper data between a computer and the arduino.
this post is divided into:
Part 1: sending data from within the arduino programme
Part 2: sending data from a windows application (using VB.Net)
Part 3: sending proper data from VB.Net
Part 4: sending data back to a PC from the arduino
Part 1: sending data from within the arduino programme
first up, the excellent arduino software tutorial. this should ensure that a lowercase letter sent (via bluetooth) to the arduino is returned (via bluetooth) in capitals. i wired up the board as suggested (see image on right) – note that the bluesmirf transmit pin (tx) will be wired up to the arduino receive pin (rx) and vice versa. i then cut and paste the tutorial into the arduino software and uploaded it to the chip. having disabled and re-enabled the smirf, and disconnected and reconnected the serial connection in teraterm, it works – sort of. in teraterm, i type in ‘a’ and get back ”β”, “b” gives me “ô”. so something a bit odd going on, but at least there’s communication!
rather than battle too long with trying to resolve what was going on there, i tried to see if i could i could flash an LED on pin 13 according to the number entered into teraterm (not the ‘serial window’ within the arduino programming environment). the following code worked:
/* Hello Software Serial Mode * -------------------------- * * turns on and off an LED on Pin 13 according to the number transmitted to the arduino via the bluesmirf. Created 17 June 2008 by Ben at cape ealing */ // include the SoftwareSerial library so you can use its functions: #include <SoftwareSerial.h> // define the pins on the arduino: 7 to rx, 6 to tx, 13 to flash #define rxPin 7 #define txPin 6 #define flashPin 13 // set up a new serial connection using pins 7 and 6 SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin); // the setup part of the script void setup() { // define pin modes for tx, rx: pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); pinMode(flashPin, OUTPUT); // set the data rate for the serial port mySerial.begin(9600);} // the main part of the script void loop() { //get the value from the receive pin int val = mySerial.read(); //turn that value from ASCII to an integer val = val - '0'; //print out the value just obtained mySerial.print(val); // print a linefeed character mySerial.println(); // flash the LED the number of times entered for (int i=0; i < val; i++){ digitalWrite(flashPin,HIGH); delay(500); digitalWrite(flashPin,LOW); delay(500); } }
Part 2: sending data from a windows application (using VB.Net)
now time to send commands from within a Windows application out via COM port 7 to the Arduino. using the same sketch as above, i then wrote the following script in visual basic (VB.Net) which opens COM7 and sends out through it the single byte “5”, which is then transmitted over bluetooth, to the arduino, which then flashes the LED on pin 13 five times.
the windows app I ran this from was a VB.Net application – the beginnings of the ASCOM driver for the binocular mirror mount (see the capeMirror software section). i wrote the entirety of that driver in the free “visual basic express” programme from microsoft (see link on left). the vb code below could easily be tested (and for free) within that environment too. It’s not adding any functionality, but it’s accessing the COM port / arduino from within a Windows application. In visual basic I created a new Project using the ‘Console Application’ template and then within that i wrote this code as the Sub Main(), click Build, then Debug->Start Debugging:
Module Module1 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Connect to Arduino over Bluetooth via the serial port. ' 'created by Ben at Cape Ealing '17 June 2008 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Sub Main() Dim Arduino_SerialPort As New IO.Ports.SerialPort 'First see if the serial port is open, if not open it If Arduino_SerialPort.IsOpen = False Then With Arduino_SerialPort .PortName = "COM7" .BaudRate = 9600 .DataBits = 8 .Parity = IO.Ports.Parity.None .StopBits = IO.Ports.StopBits.One .Encoding = System.Text.Encoding.ASCII .ReadTimeout = 5000 End With Arduino_SerialPort.Open() End If 'send one byte of data: 5 Arduino_SerialPort.Write("5") End Sub End Module
Amazingly it worked.
Part 3: sending proper data from VB.Net
Now time to send ‘longer data’ to the arduino. This little example sends 3 numbers (up to six digits long) from within a visual basic .Net application to the arduino. The arduino then flashes 3 different LED pins according to the numbers received by it. The picture on the right shows the wiring.
The following amendment to lines 23 and 24 of the VB.Net script sends an instruction which contains 3 numbers separated by semi-colons. The instruction begins with a hash. So #5;10;15 sends 3 separate variables: 5, 10 and 15.
'Arduino_SerialPort.Write("5") 'Comment out the line above and add the line below Arduino_SerialPort.Write("#5;10;15;")
On the arduino, the AFSoftwareSerial library is needed. This from ladyada as he (lad yada?) or she (lady ada?) put it “Here is a re-vamped “software serial” library that doesnt suck.”
drop it into hardware/library folder
This next sketch (with thanks to Nition who developed the tricky serial parsing bit) does the job.
/* AFSoft Serial Mode - Multi-Bits * --------------------------------------- * * Turns on and off an LED on Pin 13 according to the number transmitted to the arduino via the bluesmirf. Can now receive a number larger than 1-bit. Sending #5;10;15; will: flash Pin 11 x 5, Pin 12 x 10, Pin 13 x 15. Acknowledgements The difficult serial parsing bit was came from Nition see forum post at: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1203538464/2#2 The AFSoftwareSerial library came from ladyada. It adds the serial.available functionality. Download it here: http://www.ladyada.net/make/eshield/download.html Created 19 June 2008 * by Ben */ // include the AFSoftSerial library #include <AFSoftSerial.h> // define the pins on the arduino: 7 to rx, 6 to tx, 13 to flash #define rxPin 7 #define txPin 6 #define flashxPin 11 #define flashyPin 12 #define flashrPin 13 //define the variables for parsing serial data #define tagLength 6 // each tag ID contains 6 bytes #define hash 0x23 // "#" hash #define semicolon 0x3b // ";" semicolon #define dataRate 9600 // 9600kbps int tagIndex = 0; // counter for number of bytes read int allComplete = false; // whether all tags have been read char xVal[tagLength], yVal[tagLength], rVal[tagLength]; char thisChar; int xComplete = false; int yComplete = false; int rComplete = false; // set up a new serial connection using pins 7 and 6 AFSoftSerial mySerial = AFSoftSerial(rxPin, txPin); // the setup part of the script void setup() { // define pin modes for tx, rx pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); pinMode(flashxPin, OUTPUT); pinMode(flashyPin, OUTPUT); pinMode(flashrPin, OUTPUT); // set the data rate for the serial port mySerial.begin(dataRate);} // the main part of the script void loop() { // read in and parse serial data if (mySerial.available() > 0) { delay(1500); // wait for all data. 1.5s works fine. could be shorter. readData(); // call the function to read the data that's been received // flash the Pin 11 [xVal] number of times for (int a=0; a<atoi(xVal);a++){ digitalWrite(flashxPin,HIGH); delay(250); digitalWrite(flashxPin,LOW); delay(250); } // flash the Pin 12 [yVal] number of times for (int a=0; a<atoi(yVal);a++){ digitalWrite(flashyPin,HIGH); delay(250); digitalWrite(flashyPin,LOW); delay(250); } // flash the Pin 13 [rVal] number of times for (int a=0; a<atoi(rVal);a++){ digitalWrite(flashrPin,HIGH); delay(250); digitalWrite(flashrPin,LOW); delay(250); } } // end if } // end loop void readData() { // Reset all the variables xComplete = false; yComplete = false; rComplete = false; for (int i=0;i<5;i++){ digitalWrite(5, HIGH); xVal[i] = 0x00; yVal[i] = 0x00; rVal[i] = 0x00; } // Read the serial datachar thisChar = mySerial.read(); if (thisChar == hash) { // read all x while (xComplete == false && mySerial.available() > 0){ char thisChar = mySerial.read(); // Serial.println("x-loop"); if (thisChar == semicolon){ xComplete = true; break; } else { xVal[tagIndex] = thisChar; tagIndex++; } } tagIndex = 0; // read all y while (yComplete == false && mySerial.available() > 0){ char thisChar = mySerial.read(); // Serial.println("y-loop"); if (thisChar == semicolon){ yComplete = true; break; } else { yVal[tagIndex] = thisChar; tagIndex++; } } tagIndex = 0; // read all r while (rComplete == false && mySerial.available() > 0){ char thisChar = mySerial.read(); // Serial.println("r-loop"); if (thisChar == semicolon){ rComplete = true; break; } else { rVal[tagIndex] = thisChar; tagIndex++; } } tagIndex = 0; if (xComplete == true && yComplete == true && rComplete == true){ // Can put in debugging here } } }
Works fine.
Part 4: sending data back to a PC from the arduino
finally with a couple of amendments to the sketch and vb code the arduino can send a message back to the windows application to say that it’s finished. Here the message is: “[Arduino;Bluetooth;capeMirror]”. This is then read by the windows .Net application.
In short, the windows application is ‘waiting’ for any data received via the serial port. So here when it gets the left bracket “[“, it is programmed to collect each of the characters that follow until it gets the right bracket “]” – which tells the .Net programme that the message stream has finished. This will allow the arduino to communicate with the windows app and tell that programme when the arduino has completed the commands. The wiring is as before (on the right for quick reference).
The sketch above needs amending as follows:
1. remove the ‘//’ at line N – this will call the datacomplete function
2. add the following lines into the ‘datacomplete function’.
The vb .net code is as follows:
Module Module1 Public WithEvents Arduino_SerialPort As IO.Ports.SerialPort Public ReceivedDataYet As Boolean ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Connect to Arduino over Bluetooth via the serial port. ' 'created by Ben at Cape Ealing '17 June 2008 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Sub Main() Dim Arduino_SerialPort As New IO.Ports.SerialPort Dim RxChar As Char Dim RxMessage As String 'Empty the variables RxChar = "" RxMessage = "" 'First see if the serial port is open, if not open it If Arduino_SerialPort.IsOpen = False Then With Arduino_SerialPort .PortName = "COM7" .BaudRate = 9600 .DataBits = 8 .Parity = IO.Ports.Parity.None .StopBits = IO.Ports.StopBits.One .Encoding = System.Text.Encoding.ASCII .ReadTimeout = 5000 End With Arduino_SerialPort.Open() End If 'send the portions of data Arduino_SerialPort.Write("#5;10;15;#") 'Wait until the Arduino sends back it's message Do Until Arduino_SerialPort.BytesToRead > 0 Loop 'Collect the message one byte at a time Do RxChar = ChrW(Arduino_SerialPort.ReadByte) RxMessage = RxMessage & RxChar Loop Until RxChar = "]" 'Display the message MsgBox(RxMessage) End Sub End Module
The arduino sketch looks like this:
/* AFSoft Serial Mode - Multi-Bits * --------------------------------------- * * Turns on and off an LED on Pin 13 according to the number transmitted to the arduino via the bluesmirf. Can now receive a number larger than 1-bit. Sending #5;10;15; will: flash Pin 11 x 5, Pin 12 x 10, Pin 13 x 15. Acknowledgements The difficult serial parsing bit was came from Nition see forum post at: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1203538464/2#2 The AFSoftwareSerial library came from ladyada. It adds the serial.available functionality. Download it here: http://www.ladyada.net/make/eshield/download.html Created 19 June 2008 * by Ben */ // include the AFSoftSerial library #include <AFSoftSerial.h> // define the pins on the arduino: 7 to rx, 6 to tx, 13 to flash #define rxPin 7 #define txPin 6 #define flashxPin 11 #define flashyPin 12 #define flashrPin 13 //define the variables for parsing serial data #define tagLength 6 // each tag ID contains 6 bytes #define hash 0x23 // "#" hash #define semicolon 0x3b // ";" semicolon #define dataRate 9600 // 9600kbps int tagIndex = 0; // counter for number of bytes read int allComplete = false; // whether all tags have been read char xVal[tagLength], yVal[tagLength], rVal[tagLength]; char thisChar; int xComplete = false; int yComplete = false; int rComplete = false; // set up a new serial connection using pins 7 and 6 AFSoftSerial mySerial = AFSoftSerial(rxPin, txPin); // the setup part of the script void setup() { // define pin modes for tx, rx pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); pinMode(flashxPin, OUTPUT); pinMode(flashyPin, OUTPUT); pinMode(flashrPin, OUTPUT); // set the data rate for the serial port mySerial.begin(dataRate);} // the main part of the script void loop() { // read in and parse serial data if (mySerial.available() > 0) { delay(1500); // wait for all data to be in. 1500 works fine. could try shorter readData(); // call the function to read the data that's been received // flash the Pin 11 [xVal] number of times for (int a=0; a<atoi(xVal);a++){ digitalWrite(flashxPin,HIGH); delay(250); digitalWrite(flashxPin,LOW); delay(250); } // flash the Pin 12 [yVal] number of times for (int a=0; a<atoi(yVal);a++){ digitalWrite(flashyPin,HIGH); delay(250); digitalWrite(flashyPin,LOW); delay(250); } // flash the Pin 13 [rVal] number of times for (int a=0; a<atoi(rVal);a++){ digitalWrite(flashrPin,HIGH); delay(250); digitalWrite(flashrPin,LOW); delay(250); } // run the DataComplete procedure DataComplete(); } // end if } // end loop void readData() { // Reset all the variables xComplete = false; yComplete = false; rComplete = false; for (int i=0;i<5;i++){ digitalWrite(5, HIGH); xVal[i] = 0x00; yVal[i] = 0x00; rVal[i] = 0x00; } // Read the serial datachar thisChar = mySerial.read(); if (thisChar == hash) { // read all x while (xComplete == false && mySerial.available() > 0){ char thisChar = mySerial.read(); // Serial.println("x-loop"); if (thisChar == semicolon){ xComplete = true; break; } else { xVal[tagIndex] = thisChar; tagIndex++; } } tagIndex = 0; // read all y while (yComplete == false && mySerial.available() > 0){ char thisChar = mySerial.read(); // Serial.println("y-loop"); if (thisChar == semicolon){ yComplete = true; break; } else { yVal[tagIndex] = thisChar; tagIndex++; } } tagIndex = 0; // read all r while (rComplete == false && mySerial.available() > 0){ char thisChar = mySerial.read(); // Serial.println("r-loop"); if (thisChar == semicolon){ rComplete = true; break; } else { rVal[tagIndex] = thisChar; tagIndex++; } } tagIndex = 0; if (xComplete == true && yComplete == true && rComplete == true){ // Can put in debugging here } } } void DataComplete(){ // after all the data has been received and the LEDs flashed... mySerial.print("[Arduino;Bluetooth;capeMirror]"); }
Ben
post a comment...
you must be logged in to post a comment.