Pages: [1]   Go Down
Author Topic: VirtualWire Library Interrupt Option?  (Read 921 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
// 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!


Logged

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 533
Posts: 26947
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you would be better served to add some flags to perhaps note what state you are in, and then use millis() or  micros() to determine when the move event is over. That way you are not sitting in delay() somewhere and the sketch can be doing something useful instead of just cooling its heels waiting for delay finish.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your reply, but the delays are not the only problem. It seems that it requires very precise timing to catch the message being received.  I something similar to this that didn't work:

Code:
while(sensePing() > 25)
{
                readMsg();
scan();
enable(1, 1);
Serial.println(sensePing());
}

In addition to this, on the transmitter side I sent the message 10 times as fast as I could get the transmitter to.  I think I'm really looking for some interrupt to halt all current operations and receive the available message.  I did some further research into basic interrupts and found that a basic state change interrupt won't quite do.  You see, there is a lot of noise the the library filters out for me, so just monitoring the state of pin 2 wouldn't do.
Logged

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 533
Posts: 26947
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think that's the case.  I use VirtualWire for a remote control in my fencing scoring machine. I have a loop that does 4 or 5 things - checks for RF message coming, checks for touch detected message coming in, checks for elapsed time for the countdown timer, checks for some buttons being pressed, and I think one other thing.
So its basically cycling thru 4 if conditions, if one is active some code runs to turn on a light or change the score or something. You could do similar for your code with the servos - get one moving, check the move time on the others, check for RF messages. Most of the time it will be:
time for 1? no
time for 2? no
RF message? no
time for 1? no
time for 2? no
RF message? Yes, handle it
etc.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Alright, I'll have a look at that in my spare time and get back to you.
Logged

Pages: [1]   Go Up
Jump to: