VirtualWire + Interrupt + servo

Hello folks.

In my small project I am trying to control with buttons a servo wireless using the cheap 433MHz transmitter/receiver and the VirtualWire Library. I have one atmega 328p MUC and one arduino UNO smd . The setup is like this:

Servo is connected to UNO in which before I decide to go wireless i was using two buttons and interrupts to control the servo.
Now the buttons are on the atmega chip plus the transmitter and the servo on the Uno plus the receiver.
Problems and Quastions:

I would like to use the virtualwire to control my “external” interrupts but using software only. I have the code running but correct. It is very slow( probably to many comands in the loop) and once i press the button and the receiver get the msg and activates the interrupt it goes for ever.
and last, the signal is very noisy and some times the servo moves without me pressing the button. any way to clean the signal? cheers. Tas

my Code:
Transmitter:

  #include <VirtualWire.h>

void setup()
{
   // Serial.begin(9600);	  // Debugging only
   // Serial.println("setup");

    // Initialise the IO and ISR
   // vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(2000);	 // Bits per sec
        vw_set_tx_pin(3); 
        
        pinMode(8, INPUT);
        pinMode(9, INPUT);

digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
}

void loop()
{
  char *msg;
  
  if(digitalRead(8) == LOW){
    char *msg = "5";
      digitalWrite(13, true); // Flash a light to show transmitting
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx(); // Wait until the whole message is gone
    digitalWrite(13, false);}
  if(digitalRead(9) == LOW){
    char *msg = "6";
      digitalWrite(13, true); // Flash a light to show transmitting
    vw_send((uint8_t *)msg, strlen(msg));
    vw_wait_tx(); // Wait until the whole message is gone
    digitalWrite(13, false);}
}

Receiver ( the hard part) :~ :

#include <ServoTimer2.h> 
#include <EEPROM.h>
#include <util/delay.h>
#include <VirtualWire.h>

ServoTimer2 myservo; 

/* CHANGE ME */
// Servo limit - These number will change depending on how you installed your servo
//   Set MANUAL_MODE = 1, connect a potentiometer to pin 3 and open the serial monitor
//   Move to the lowest and highest gear to set these variables
int SERVO_STOP_LOW = 2100;
int SERVO_STOP_HIGH = 740;

#define MANUAL_MODE 1

// variable to read the value from the analog pin 
int val;    
int potpin = 3;  
//int servo_power_pin = 6;
int led_pin = 10;

// Current servo position
int currentPos = 1000;
int currentPosAddr = 0;

// Number of positions to move when a button is pused 
int servo_step_size =100 ;

// Flag set in the interrupt to signal a gear change
bool pendingShift = true;

void setup() 
{ //pinMode(4, INPUT); 
  vw_setup(2000);	 // Bits per sec
    vw_set_rx_pin(4);
    vw_rx_start();       // Start the receiver PLL running
  //pinMode(servo_power_pin, OUTPUT);   
  pinMode(led_pin, OUTPUT); 
  pinMode(11, OUTPUT); 
  digitalWrite(2, HIGH);
  digitalWrite(3, HIGH);  
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
  Serial.begin(9600);
  
  //digitalWrite(servo_power_pin, LOW);
  
  attachInterrupt(0, shiftUp, FALLING);
  attachInterrupt(1, shiftDown, FALLING);
  
  // Remember last position
  currentPos = EEPROM.read(currentPosAddr);
} 

void shiftUp()
{
  if ( pendingShift == true ) return;
  
  // wait for button to stop bouncing
  delay(50);
  
  currentPos -= servo_step_size;
  if ( currentPos < SERVO_STOP_HIGH) 
    currentPos = SERVO_STOP_HIGH;
    
  pendingShift = true;
  
  Serial.println("Shift up ");
  Serial.println(currentPos);
}

void shiftDown()
{
  if ( pendingShift == true ) return;
  
  // wait for button to stop bouncing
  delay(50);  
  
  currentPos += servo_step_size;
  if ( currentPos > SERVO_STOP_LOW) 
    currentPos = SERVO_STOP_LOW;
    
  pendingShift = true;
  
  Serial.println("Shift down ");
  Serial.println(currentPos);
}

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;
	Serial.print("Got: ");
        //Serial.print(buf);
        //Serial.print(buflen);
	for (i = 0; i < buflen; i++)
	{
	    Serial.print(buf[i]);
        if(buf[i] == '5'){digitalWrite(2, LOW);
                           delay(10);
                          //digitalWrite(2, HIGH);
                        digitalWrite(11, HIGH);}
        if(buf[i] == '6'){digitalWrite(3, LOW);
                          delay(10);
                          //digitalWrite(3,HIGH);
                        digitalWrite(11, LOW);}
	}
	Serial.println("");
        digitalWrite(13, false);
    }
    //digitalWrite(2, HIGH);
  //digitalWrite(3, HIGH);
#if MANUAL_MODE
    
  if ( pendingShift )
  {
    


    Serial.println("ON");
    digitalWrite(led_pin, HIGH);
   // digitalWrite(servo_power_pin, HIGH);
    _delay_ms(15);
    
    myservo.write(currentPos);
    
    // Save last know position
    EEPROM.write(currentPosAddr, currentPos);
    
    // wait for servo to finish
    _delay_ms(200); 
    
    Serial.println(currentPos);
    digitalWrite(led_pin, LOW);
   // digitalWrite(servo_power_pin, LOW);
    
    pendingShift = false;
  }
#else
  
  // This code controls the servo with a POT
  // To use it change MANUAL_MODE 1
  
  digitalWrite(servo_power_pin, HIGH);
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023) 
  val = map(val, 0, 1023, 0, 179);     // scale it to use it with the servo (value between 0 and 180) 
  myservo.write(val);                  // sets the servo position according to the scaled value 
  Serial.println(val);
  delay(15);                           // waits for the servo to get there 
#endif
}

I'm not sure why you ever needed interrupts but I certainly don't understand what they are doing in the receiver code - or why there is any need for debouncing. All that should be done (if it is necessary at all) on the Arduino with the switches attached to it. All the wireless code needs to send is, perhaps, A for one switch and B for the other switch.

The code seem very long if all it has to do is receive one or two characters to tell it which way to move a servo. Why not something like (pseudo code)

inChar = valueFromRadio
if (inChar == 'A') {
   servoToPosition X
}
else {
  servoToPosition Y
}

...R

Thanks for the reply Robin.

Yeah you are right about the interrupt.. my coding skills are not that great.. I also tried what you said but I was receiving noise and the motor was going crazy up and down. Any way to filter the noise? Also should I put everything in the loop or make a new void? Cheers Tas

Also should I put everything in the loop or make a new void?

Yes, you should make a new void, and put the Arduino in it until you learn proper terminology. void is a return type for a FUNCTION!

I'm doing almost the same thing. What I have found is VirtualWire.h and servo.h don't get along with each other. ServoTimer2.h may get around this? Have not tried it. I'm also using IRremote.h to get the codes to send. I have ended up writing my own RF send and receive. They do not use any interrupts or timers, and is working very well.

Thanks for that Paul.. in my personal opinion if you fed up of stupid people using wrong terminology just ignore us until we learn as all of us do wrong terminology at the begin..

Cheers
Tas

Hi Steinie thanks for the reply.

Yeah I used the servotimer2 for the servo but my issue now is the background noise I get in the receiver. I'll check what you said about the remote library. One question tho.. did you suffer from a background noise on the receiver.

Cheers
Tas

did you suffer from a background noise on the receiver.

Well, yes and no. Is it background noise or corruption of data? Two different things. Background noise may be from something near by sending on the 433 MHz frequency. If so, then there is not much you can do. However if it's corruption of data. It's probably due to a lack of a Ground Plane. Google: Ground Plane Antenna. Make sure you have a 6.5 - 6.75" antenna. Try to place the radios directly above the Arduino. That will make the Arduino the Ground Plane. You can also place the radios above a metal plate that is connected to ground. Don't let the radio Tx or Rx touch the plate. You can use 4 wires, same length as the antenna, in a X pattern, under the Tx and Rx, connected to ground.

Zeledas:
I also tried what you said but I was receiving noise and the motor was going crazy up and down. Any way to filter the noise? Also should I put everything in the loop or make a new void? Cheers Tas

Posting your new code would be a good start.

...R