*** Solved here means the problem disappeared after applying some brute OCD copy/paste/merge code. Exact origin of it? Well I choose not to dwell on it.
Well, while developing my remote control/receiver node all was well when unidirectional communication... and then I decided to add bidirectionality in order to get back feedback/telemetric data.
I'm using RF24L01+ radio modules and the RF24 library to handle them.
The Remote Control sends a struct with X & Y integer values and an array of booleans corresponding to button pushes.
That works great, X values makes the test servo sweep on the receiver node, and the button pushes toggle LEDs. I've also read their values via serial connection and they are what they should be (that is, what is sent from the transmitter is what is got in the receiver.
I've now associated the buttons pushes in order to decrement/increment a variable (which it does fine as tested by serial reading). The variable ranges from 70 to 120 (in increments of 10). However, when I send it over with radio.write() the values I get on the remote control lcd... are somewhat different...
Send 70 .... get 17990. I've already been told that 70 == 0x46 and that 17990 == 0x4646 ... so there's a duplicating thinguie of sorts...
the problem is that I don't know why it happens... the TX --> RX works fine... can't see why RX --> TX is failing like this...
I only suspect it may have something to do with the second paramenter from the write() method...
http://maniacbug.github.com/RF24/classRF24.html#a4cd4c198a47704db20b6b5cf0731cd58
but I've tried a few options (half-blindly)... but no success...
If there's no fault there... I guess the other culprit would be the LCD library? but I have no idea why it would be transforming the 70 into 17990 ... but then again, what do I know? that's why I am asking...
Below follows the code, with dirty comment outs and everything so you can see some of the fiddlings I've been doing...
Remote control code:
// include the library code: #include <LiquidCrystal.h> #include <SPI.h> #include "nRF24L01.h" #include "RF24.h"// analog pin reading V_out/V2 from voltage divider
const int battPin = A5;// button ‘pad’ pin
const int buttonPin = A3;// Button setup schematics
// Analog pin 5
// |
//Ground–1K–|--------|--------|-------|
// | | | |
// btn1 btn2 btn3 btn4
// | | | |
// 220 Ohm 390 Ohm 680 Ohm 2.2K
// |--------|--------|-------|-- +5Vint j = 1;
// ‘j’ is the integer used in scanning the array designating column number
// these ranges below are dependent on the schematics above and may
// need to be adjusted manually to compensate for various factors
int Button[15][3] = {{1, 836, 840}, // button 1
{2, 732, 738}, // button 2
{3, 600, 625}, // button 3
{4, 310, 335}, // button 4
{5, 890, 900}, // button 1 + 2
{6, 870, 880}, // button 1 + 3
{7, 840, 860}, // button 1 + 4
{8, 810, 830}, // button 2 + 3
{9, 760, 780}, // button 2 + 4
{10, 665, 685} // button 3 + 4
};int label = 0; // for reporting the button label
int counter = 0; // how many times we have seen new value
long time = 0; // the last time the output pin was sampled
int debounce_count = 5; // number of millis/samples to consider before declaring a debounced input
int current_state = 0; // the debounced input valueint ButtonVal;
int lift;
// = 60;
//int joypad[6]; // array – stores the values to send
RF24 radio(9,10);
//const uint64_t pipe = 0xE8E8F0F0E1LL;const uint64_t pipes[2] = {
0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };// default reference on circuit used (5.0, 3.3, 1.1)
const double refV = 5.0;
// How many volts does 1 ADC measure?
const double V_incr = refV/1024.0;// values of resistances used for voltage divider
const double R1 = 68.4;
const double R2 = 46.6;// determine voltage divider ratio
const double voltageRatio = (R2/(R1 + R2));
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 7, 5, 4, 3, 2);// define a type struture
// to carry lovely messages
typedef struct{
int X;
int Y;
boolean buttons[4];
}
Payload;Payload package;
typedef struct{
int X;
int rudderAngle;
int Z;
}
Feedback;Feedback telemetrics;
void setup() {
Serial.begin(57600);
radio.begin();
//radio.openWritingPipe(pipe);radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
pinMode(buttonPin, INPUT);
// set up the LCD’s number of COLUMNS and ROWS:
lcd.begin(16, 2);
// Print a message to the LCD.
//lcd.print("Batt = ");
lcd.setCursor(0, 1);
lcd.print("X: ");
lcd.setCursor(7, 1);
lcd.print("Y: ");
}void loop() {
// monitor battery voltage on remote
int val = analogRead(battPin);
double battV = VoltageCheck(val);
//lcd.setCursor(7, 0);
//lcd.print(battV);
package.X = analogRead(A0);
delay(1);
package.Y = analogRead(A1);
delay(1);
// LCD DEBUGGING
lcd.setCursor(2, 1);
lcd.print(package.X);
lcd.setCursor(9, 1);
lcd.print(package.Y);
// If we have gone on to the next millisecond
if (millis() != time)
{
// check analog pin for the button value and save it to ButtonVal
ButtonVal = analogRead(buttonPin);
delay(1);
//Serial.println(ButtonVal); // DEBUG
if(ButtonVal == current_state && counter >0)
{
counter–;
}
if(ButtonVal != current_state)
{
counter++;
}
// If ButtonVal has shown the same value for long enough let’s switch it
if (counter >= debounce_count)
{
counter = 0;
current_state = ButtonVal;
//Checks which button or button combo has been pressed
if (ButtonVal > 100){
ButtonCheck();}else{package.buttons[0] = 0;
package.buttons[1] = 0;
package.buttons[2] = 0;
package.buttons[3] = 0;}
}
time = millis();
} // closes if(millis() != time)//bool ok = radio.write( &duino2, sizeof(duino2) );
// Send radio message below
//radio.write( joypad, sizeof(joypad) );radio.stopListening();
bool ok = radio.write( &package, sizeof(package) );
radio.startListening();delay(20);
//if (radio.available() )
//{// Dump the payloads until we’ve gotten everything
//uint8_t len;
bool done = false;
while (!done)
{
// Fetch the payload, and see if this was the last one.
//len = radio.getDynamicPayloadSize();
//done = radio.read( receive_payload, len );done = radio.read(&lift, sizeof(int) );
// Put a zero at the end for easy printing
//receive_payload[len] = 0;// Spew it
//printf(“Got payload size=%i value=%s\n\r”,len,receive_payload);
}
lcd.setCursor(0,0);
lcd.print(lift);// First, stop listening so we can talk
//radio.stopListening();
//}
//radio.read(&lift, sizeof(int) );
//radio.read(&telemetrics, sizeof(telemetrics) );// REGULAR – PREVIOUS here
// radio.write( &package, sizeof(package) );
// LCD DEBUGGING
//lcd.setCursor(12, 0);//lcd.print(“L:”);
// lcd.setCursor(0,0);
// lcd.print(lift);//lcd.setCursor(0,0);
//lcd.print(telemetrics.Z);
//lcd.setCursor(6,0);
//lcd.print(telemetrics.X);
//lcd.setCursor(10,0);
//lcd.print(telemetrics.rudderAngle);
// lcd.print(package.buttons[0]);
// lcd.print(package.buttons[1]);
// lcd.print(package.buttons[2]);
// lcd.print(package.buttons[3]);
}// read that battery voltage, biaaaatch
double VoltageCheck(int v){double pinV = v * V_incr;
double volts_in = pinV * 1/voltageRatio;return volts_in;
}// checks which f’king button (or combo) has been pressed, if any
void ButtonCheck()
{
// loop for scanning the button array.
for(int i = 0; i <= 10; i++)
{
// checks the ButtonVal against the high and low vales in the array
if(ButtonVal >= Button[i][j] && ButtonVal <= Button[i][j+1])
{
// stores the button number to a variable
label = Button[i][0];
switch (label) {
case 1:
package.buttons[0] = 1;
package.buttons[1] = 0;
package.buttons[2] = 0;
package.buttons[3] = 0;
//Serial.println(“button 1”);
break;
case 2:
package.buttons[0] = 0;
package.buttons[1] = 1;
package.buttons[2] = 0;
package.buttons[3] = 0;
//Serial.println(“button 2”);
break;
case 3:
package.buttons[0] = 0;
package.buttons[1] = 0;
package.buttons[2] = 1;
package.buttons[3] = 0;
//Serial.println(“button 3”);
break;
case 4:
package.buttons[0] = 0;
package.buttons[1] = 0;
package.buttons[2] = 0;
package.buttons[3] = 1;
//Serial.println(“button 4”);
break;
case 5:
//Serial.println(“button 1 + 2”);
package.buttons[0] = 1;
package.buttons[1] = 1;
package.buttons[2] = 0;
package.buttons[3] = 0;
break;
case 6:
//Serial.println(“button 1 + 3”);
package.buttons[0] = 1;
package.buttons[1] = 0;
package.buttons[2] = 1;
package.buttons[3] = 0;
break;
case 7:
//Serial.println(“button 1 + 4”);
package.buttons[0] = 1;
package.buttons[1] = 0;
package.buttons[2] = 0;
package.buttons[3] = 1;
break;
case 8:
//Serial.println(“button 2 + 3”);
package.buttons[0] = 0;
package.buttons[1] = 1;
package.buttons[2] = 1;
package.buttons[3] = 0;
break;
case 9:
//Serial.println(“button 2 + 4”);
package.buttons[0] = 0;
package.buttons[1] = 1;
package.buttons[2] = 0;
package.buttons[3] = 1;
break;
case 10:
//Serial.println(“button 3 + 4”);
package.buttons[0] = 0;
package.buttons[1] = 0;
package.buttons[2] = 1;
package.buttons[3] = 1;
break;
} // close switch
}
}
}
Receiver node code:
// Lovely code for the (mostly) receiver (RX) node
#include <Servo.h>
#include <SPI.h>
#include “nRF24L01.h”
#include “RF24.h”
//int commands[6];// define a type struture
// to carry lovely messages
typedef struct{
int X;
int Y;
boolean buttons[4];
}
Payload;Payload package;
typedef struct{
int X;
int rudderAng;
int Z;
}
Feedback;Feedback telemetrics;
int oldAngle, newAngle = 0; // servo positions
long previousMillis = 0; // timer for servo
long previousButtonMillis = 0; // timer for buttons
const int interval = 30; // interval to update servo position
const int binterval = 60;Servo rudder;
//int lift[1];
int lift_ang;
// pretty debug LEDs
const int b1 = 2;
const int b2 = 3;
const int b3 = 4;
const int b4 = 5;// LED’s state
int b1state = LOW;
int b2state = LOW;
int b3state = LOW;
int b4state = LOW;
RF24 radio(9, 10);
//const uint64_t pipe = 0xE8E8F0F0E1LL;const uint64_t pipes[2] = {
0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
void setup(void)
{
Serial.begin(57600);radio.begin();
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
radio.startListening();
rudder.attach(7);
pinMode(b1, OUTPUT);
pinMode(b2, OUTPUT);
pinMode(b3, OUTPUT);
pinMode(b4, OUTPUT);digitalWrite(b3, HIGH); // DEBUG
//lift[0] = 70;lift_ang = 70;
}
void loop(void)
{
delay(10);
if ( radio.available() )
{
// Dump the payloads until we’ve gotten everything
bool done = false;
while (!done)
{
// Fetch the payload, and see if this was the last one.
done = radio.read( &package, sizeof(package) );
}
// See what to do with this???
//radio.stopListening();//radio.write( &duino1, sizeof(duino2) );
//radio.startListening();
int X = package.X;
int Y = package.Y;// if (package.buttons[1] == 1 && lift[0] < 120)
// {
// lift[0] += 10;
// }// if (package.buttons[3] == 1 && lift[0] > 70)
// {
// lift[0] -= 10;
// }// Serial.println(lift[0]);
//}
//radio.stopListening();
//telemetrics.Z = lift[0];
//radio.write( lift, sizeof(lift[0]) );
//radio.write( &telemetrics, sizeof(telemetrics) );
//radio.startListening();
if (X > 485 && X < 525 ) // joystick is centered
{
newAngle = 87; // 87 = servo in center position
}
if (X < 490)
{
newAngle = (map(X, 484, 140, 88, 130));
}
if (X > 530)
{
newAngle = (map(X, 526, 830, 86, 35));
}
unsigned long currentMillis = millis();
// Issue command only if desired position changes and interval is over
if(oldAngle != newAngle && currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
oldAngle = newAngle;
rudder.write(newAngle); // tell servo to go to position in variable ‘pos’
} // close if millis-land
//}
currentMillis = millis();
if (currentMillis - previousButtonMillis > binterval) {
if (package.buttons[0] == 1){
if(b1state == LOW){
b1state = HIGH; }
else{ b1state = LOW; }
digitalWrite(b1, b1state);if(lift_ang != 90){ lift_ang = 90; }
}
if (package.buttons[1] == 1){
if(b2state == LOW){
b2state = HIGH; }
else{ b2state = LOW; }
digitalWrite(b2, b2state);if(lift_ang < 120){ lift_ang += 10; }
}
if (package.buttons[2] == 1){
if(b3state == LOW){
b3state = HIGH; }
else{ b3state = LOW; }
digitalWrite(b3, b3state);
}
if (package.buttons[3] == 1){
if(b4state == LOW){
b4state = HIGH; }
else{ b4state = LOW; }
digitalWrite(b4, b4state);if(lift_ang > 70){ lift_ang -= 10; }
}
previousButtonMillis = currentMillis;
} // close if millis-land (secundary test) – button millisradio.stopListening();
delay(20);
//telemetrics.Z = lift_ang;
//telemetrics.X = X;
//telemetrics.rudderAng = newAngle;
//if (radio.available() )
//{
radio.write( &lift_ang, sizeof(int) );
//radio.write( &telemetrics, sizeof(telemetrics) );
//}
radio.startListening();//Serial.println(package.X);
//Serial.println(telemetrics.Z);
//Serial.println(telemetrics.X);
//Serial.println(telemetrics.rudderAng);
//Serial.println(“break”);
//} // close while(!done)
} // close if(radio.available() )
else { Serial.println(“No radio available”); }
} // close loop()