So here's my project/problem. I am working on an autonomous rover with the Arduino uno. It has all sorts of gadgets; ping, servos, etc. But my issue is with the communication device I am using. It's the FS1000a and XY-MK-5V radio rx tx set (got them off ebay for $2). I did some googling and fond that the VirtualWire library did a great job of handling these devices. Now, as I said the rover has an autonomous mode, but i would also like to be able to control it manually via the rf kit. It would also be neat to be able to do things like pause the autonomous cycle. The thing is, when i sent the command for the rover to change "modes" , the receiver doesn't always receive the message. I have determined that this is because it isn't constantly listening for a message (at any given time the code could very well be in a delay() ). So I think this means that i need to put an interrupt on the rx pin of the receiver. Here's some code to better illustrate my problem.
// Do not remove the include below
#include "Rover.h"
#include "HardwareSerial.h"
#include "ServoTimer2.h"
#include "NewPing.h"
#define RX 2
#define TRIGGER 9
#define ECHO 10
#define ENA 5
#define ENB 6
#define MA 7
#define MB 8
#define SERVO1 A0
#define SERVO2 A1
#define SERVO3 A2
#define LED 13
ServoTimer2 servo1;
ServoTimer2 servo2;
ServoTimer2 servo3;
NewPing ping(TRIGGER, ECHO, 200);
int mode = 1; // this is the "mode" the rover is in. 0 = auto, 1 = pause, 2 = manual
void setup()
{
Serial.begin(9600);
pinMode(MA, OUTPUT);
pinMode(MB, OUTPUT);
pinMode(TRIGGER, OUTPUT);
pinMode(ECHO, INPUT);
pinMode(LED, OUTPUT);
vw_set_rx_pin(RX);
vw_set_ptt_inverted(true);
vw_set_ptt_pin(3);
vw_setup(2000);
vw_rx_start();
servo1.attach(SERVO1);
servo2.attach(SERVO2);
servo3.attach(SERVO3);
servoWrite(90, servo1);
enable(0, 0);
Serial.println("Setup Complete");
}
void loop()
{
readMsg(); //checks for a message
switch(mode)
{
case 0:
mode0(); //begin autonomous loop
break;
case 2:
mode2(); // TODO: listen for more commands in manual mode;
break;
}
}
void mode0()
{
setFwd();
enable(0, 0);
servoWrite(90, servo1);
delay(500);
Serial.println(sensePing());
while(sensePing() > 25)
{
scan();
readMsg();
enable(1, 1);
Serial.println(sensePing());
delay(20);
}
enable(0, 0);
switch(senseRoute())
{
case 0:
while(sensePing() < 35)
{
enable(0,1);
delay(60);
}
break;
case 1:
while(sensePing() < 35)
{
enable(1, 0);
delay(60);
}
break;
}
}
void mode2()
{
//TODO
}
int pos = 90;
int dir = 10;
void scan()
{
pos += dir;
servoWrite(pos, servo1);
if(pos > 120)
dir = -10;
else if(pos < 60)
dir = 10;
}
void readMsg()
{
int msg = getMsg();
if(msg != 99)
{ // change modes based on the integer that the rover received.
if(msg == 0)
mode = 0;
else if(msg == 1)
mode = 1;
else if(msg == 2)
mode = 2;
}
}
int getMsg()
{
int num = 99;
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen))
{
digitalWrite(13, HIGH);
num = atoi((char *)buf);
Serial.println(num);
digitalWrite(13, LOW);
}
return num;
}
int sensePing()
{
int dist = ping.ping()/US_ROUNDTRIP_CM;
if(dist == 0)
dist = 1000;
return dist;
}
void servoWrite(int val, ServoTimer2 servo)
{
val = map(val, 0, 180, 540, 2600);
servo.write(val);
}
int senseRoute()
{
int max = 100;
int maxPos = 90;
servoWrite(0, servo1);
delay(350);
for(int i = 0; i <= 180; i+=20)
{
servoWrite(i, servo1);
delay(100);
int dist = sensePing();
if(dist < max)
{
max = dist;
maxPos = i;
}
}
servoWrite(maxPos, servo1);
delay(500);
if(max < 10 && maxPos > 50 && maxPos < 130)
setBack();
if(max < 40)
{
if(maxPos < 90)
return 1;
else
return 0;
}
return 99;
}
void enable(int a, int b)
{
digitalWrite(ENA, a);
digitalWrite(ENB, b);
}
void setFwd()
{
digitalWrite(MA, HIGH);
digitalWrite(MB, HIGH);
}
void setBack()
{
digitalWrite(MA, LOW);
digitalWrite(MB, LOW);
}
You may not have needed to look at all my code but it can't hurt. So, what I think I need to do is put the readMsg() method inside an interrupt listening for the rx module to receive something. If anyone could help me out with how exactly to do this, i would be very grateful. Thanks!