I have a set up where Processing reads serial data from my iPhone and send this message to Arduino to actuate motors.
I now want this process to be wireless as the motors are a propulsion system for a helium blimp; am playing around with VirtualWire to do so.
Arduino1 (connected to computer) is the transmitter (receiving data from iPhone/Processing),
Arduino2 receives this message and actuates the motors.
The communication that is working:
iPhone>Processing>Arduino1>transmit
Issue:
Arduino2 is not receiving (code issue; all hardware working fine with other VW codes).
Am a new kid on the block in terms of VirtualWire, I suspect I'm mishandling data/datatypes (?!)
thoughts?
thanks in advance...
//TRANSMITTER CODE
#include <AFMotor.h>
#include <VirtualWire.h>
int msg = 0; //MSG from iphone>processing
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("wireless setup");
//wireless setup
vw_setup(2000); // Bits per sec
pinMode (9, OUTPUT);
}
void loop() {
if (Serial.available() > 0) { // Check if there is a new message
msg = Serial.read(); // Put the serial input into the message
Serial.println(msg);
vw_send((byte *)msg, 2);
delay(200);
}
}
//RECEIVERCODE
#include <AFMotor.h>
#include <VirtualWire.h>
int message = 0;
int ledPin = 13;
int dly = 2;
//DIRECTIONAL MOTORS
AF_DCMotor motor(1, MOTOR12_64KHZ);
AF_DCMotor motor2(1, MOTOR12_64KHZ);
AF_DCMotor motor3(3, MOTOR12_64KHZ);
AF_DCMotor motor4(3, MOTOR12_64KHZ);
// LANDING PROPELLORS
AF_DCMotor motor5(2, MOTOR12_64KHZ);
AF_DCMotor motor6(2, MOTOR12_64KHZ);
AF_DCMotor motor7(2, MOTOR12_64KHZ);
AF_DCMotor motor8(2, MOTOR12_64KHZ);
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("Motor test!");
Serial.println("wireless setup");
//wireless setup
vw_setup(2000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
//motor setup
motor.setSpeed(255);
motor2.setSpeed(255);// set the speed to 200/255
motor3.setSpeed(255);
motor4.setSpeed(255);
motor5.setSpeed(1000);
motor6.setSpeed(1000);
motor7.setSpeed(1000);
motor8.setSpeed(1000);
pinMode (9, OUTPUT);
}
void loop() {
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking
{
int i;
// Message with a good checksum received, dump HEX
Serial.print("Got: ");
for (i = 0; i < buflen; i++)
{
Serial.print(buf[i], HEX);
Serial.print(" ");
}
Serial.println("");
}
// if (Serial.available() > 0) { // Check if there is a new message
//MOTOR ACTIONS
//LEFT MOTOR--------------------------------------------------------------
if(message == 'A'){
Serial.print("fwd");
motor.run(FORWARD); // turn it on going forward
motor2.run(FORWARD);
delay(dly);
}
if (message == 'C'){
Serial.print("back");
motor.run(BACKWARD); // the other way
motor2.run(BACKWARD);
delay(dly);
}
if (message == 'B'){
Serial.print("stop");
motor.run(RELEASE); // stopped
motor2.run(RELEASE);
delay(dly);
}
//RIGHT MOTOR--------------------------------------------------------------
if(message == 'F'){
Serial.print("fwd");
motor3.run(FORWARD); // turn it on going forward
motor4.run(FORWARD);
delay(dly);
}
if (message == 'D'){
Serial.print("BAck");
motor3.run(BACKWARD); // the other way
motor4.run(BACKWARD);
delay(dly);
}
if (message == 'E'){
Serial.print("stop");
motor3.run(RELEASE); // stopped
motor4.run(RELEASE);
delay(dly);
}
//LANDING MOTOR--------------------------------------------------------------
if(message == 'X'){
Serial.print("land");
motor5.run(BACKWARD); // turn it on going forward
motor6.run(BACKWARD);
motor7.run(BACKWARD); // turn it on going forward
motor8.run(BACKWARD);
delay(dly);
}
if(message == 'Y'){
Serial.print("stopLand");
motor5.run(RELEASE); // stopped
motor6.run(RELEASE);
motor7.run(RELEASE); // stopped
motor8.run(RELEASE);
delay(dly);
}
// }
}
msg = Serial.read(); // Put the serial input into the message
Serial.println(msg);
vw_send((byte *)msg, 2);
Read one byte from the serial port, and send both of them. Why?
Arduino1's message (currently) sends a series of letters whilst Arduino2 receives a series of digits.
help?
This doesn't make sense. Print, on the sender, the byte(s) being sent, in the same way that you are printing them on the receiver.
Show some examples of what you are sending, and what you are receiving. If you are (trying to) send an A, and you are receiving a 65, then everything is working.
after a lot more research and progress, I have developed the code quite some bit and it is almost working...I'm one step away from it functioning properly... calling on any VirtualWire gurus out there...
And the iPhone data is feeding into the transmitter perfectly.
The transmitter and receiver communicate nicely. Sometimes. See following:
This all works except the character fails to transmit to the VWire
//TRANSMITTER CODE
#include <VirtualWire.h>
int serIn; // var that will hold the bytes-in read from the serialBuffer
char serInString[25]; // array that will hold the different bytes 100=100characters;
// -> you must state how long the array will be else it won't work.
int serInIndx = 0; // index of serInString[] in which to insert the next incoming byte
int serOutIndx = 0; // index of the outgoing serInString[] array;
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
vw_setup(2000); // Bits per sec
// pinMode (9, OUTPUT);
}
void loop() {
/// - First lines read anything that has been received into the serial buffer
/// into an array called "serInString"
int sb;
if(Serial.available()) {
while (Serial.available()){
sb = Serial.read();
serInString[serInIndx] = sb;
serInIndx++;
}
}
/// - Now 'replay' the string one character at a time from "serInString"
/// out to the print function (with hex version in Sq Brackets) and to the VWire
/// eg 'hello' is h[68] e[65] l[6c] l[6c] o[6f]
/// eg '789' is 7[37] 8[38] 9[39]
if( serInIndx > 0) {
//loop through all bytes in the array and print them out/send
for(serOutIndx=0; serOutIndx < serInIndx; serOutIndx++) {
if(serInIndx>15){ // if the buffer is heading towards an overflow then ignore everything in it and start again
break;
}
Serial.print(serInString[serOutIndx]); //print to the serial monitor
char *msg=serInString[serOutIndx];
vw_send((uint8_t *)serInString[serOutIndx], strlen(msg));//send one character message msg to receiver
vw_send((uint8_t *)serInString[serOutIndx], 1);
vw_wait_tx();
}
//reset all the functions to be able to fill the string back with content
serOutIndx = 0;
serInIndx = 0;
Serial.println();
}
}
However, transmitting a simple “h” at the very bottom of the loop does send the ‘h’ successfully through VWire. There seems to be some scope issue and vw_send only works when at the root level of loop().
//TRANSMITTER CODE
#include <VirtualWire.h>
int serIn; // var that will hold the bytes-in read from the serialBuffer
char serInString[25]; // array that will hold the different bytes 100=100characters;
// -> you must state how long the array will be else it won't work.
int serInIndx = 0; // index of serInString[] in which to insert the next incoming byte
int serOutIndx = 0; // index of the outgoing serInString[] array;
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
vw_setup(2000); // Bits per sec
// pinMode (9, OUTPUT);
}
void loop() {
/// - First lines read anything that has been received into the serial buffer
/// into an array called "serInString"
int sb;
if(Serial.available()) {
while (Serial.available()){
sb = Serial.read();
serInString[serInIndx] = sb;
serInIndx++;
}
}
/// - Now 'replay' the string one character at a time from "serInString"
/// out to the print function (with hex version in Sq Brackets) and to the VWire
/// eg 'hello' is h[68] e[65] l[6c] l[6c] o[6f]
/// eg '789' is 7[37] 8[38] 9[39]
if( serInIndx > 0) {
//loop through all bytes in the array and print them out/send
for(serOutIndx=0; serOutIndx < serInIndx; serOutIndx++) {
if(serInIndx>15){ // if the buffer is heading towards an overflow then ignore everything in it and start again
break;
}
Serial.print(serInString[serOutIndx]); //print to the serial monitor
// char *msg=serInString[serOutIndx];
// vw_send((uint8_t *)serInString[serOutIndx], strlen(msg));//send one character message msg to receiver
// vw_send((uint8_t *)serInString[serOutIndx], 2);
// vw_wait_tx();
}
//reset all the functions to be able to fill the string back with content
serOutIndx = 0;
serInIndx = 0;
Serial.println();
}
const char *msg = "h";
vw_send((uint8_t *)msg, strlen(msg));
delay(400);
}
I have tried using the sendString() function right after the loop:
char *msg=serInString[serOutIndx];
vw_send((uint8_t *)serInString[serOutIndx], strlen(msg));//send one character message msg to receiver
You define a pointer, and point it at one character. You do this so you can determine the length of the one character string.
A string (what strlen expects as input) must be a NULL terminated array of characters, not a single character. Why you need to measure the length of a character is a mystery. Will it ever be other than 1?
I see what you are saying about the string thing - it ended that way through some trial and error to address issues and was ugly as you pointed out. I have re-written the code to focus on the issue at hand. It sends a complete string through the function now.
The code is below.
The issue is that the receiver is receiving scrambled output.
If LINES AA are commented out and LINE B uncommented the receiving end gets "Hello" successfully.
Got: 68(h) 65(e) 6C(l) 6C(l) 6F(o)
If both sets are uncommented then Hello is mangled up with random characters (not a mix of the incoming characters and hello).
Most weirdly, if LINES AA are commented out and LINE B uncommented and the iPhone transmition comes into the serial in, it actually corrupts the "Hello"! The incoming data rate can be at 9600 which is of course higher than the outgoing of 2000. Can that incoming stream swamp the device?
As a side comment - if LINES AA are replaced with just a string eg
sendString("hello"), it still scrambles.
Essentially, somehow the incoming Serial data stream is interfering with the VWire TX stream.
I hope that provides focus for the problem issue - quite a challenge...
//TRANSMITTER CODE
#include <VirtualWire.h>
int TXpin=12; //Sets pit to VWtransmit on - 13 for LED; 12 for real transmitter
int serIn; // var that will hold the bytes-in read from the serialBuffer
char serInString[25]; // array that will hold the different bytes 100=100characters;
// -> you must state how long the array will be else it won't work.
int serInIndx = 0; // index of serInString[] in which to insert the next incoming byte
int serOutIndx = 0; // index of the outgoing serInString[] array;
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
vw_setup(2000); // Bits per sec
vw_set_tx_pin(TXpin);
}
void loop() {
/// - First lines read anything that has been received into the serial buffer
/// into an array called "serInString"
int sb;
if(Serial.available()) {
while (Serial.available()){
sb = Serial.read();
serInString[serInIndx] = sb;
serInIndx++;
if(serInIndx>5){break;} // If the serial input is getting too ahead just send & drop it
}
}
if(serInIndx>0){ //If there is a string to send then send it
sendString(serInString); // LINES AA
Serial.print(serInString);// LINES AA
}
//reset the index to strat again
serInIndx = 0;
// sendString("hello"); // LINE BB
}
void sendString(String s){
uint8_t Mybuf[VW_MAX_MESSAGE_LEN];
for(int i=0;i<s.length();i++) {Mybuf[i]=(uint8_t)s.charAt(i);}
vw_send(Mybuf,s.length());
vw_wait_tx();
}