Nico Hennrich
Published

Upcycling a Radio Remote Control

I found an old 35MHz remote control and started to reuse it for building a programmable 2.4GHz Arduino based remote control with telemetry.

AdvancedWork in progress10 hours308
Upcycling a Radio Remote Control

Things used in this project

Hardware components

Arduino UNO & Genuino UNO
Arduino UNO & Genuino UNO
×1
Arduino Nano R3
Arduino Nano R3
×2
nRF24 Module (Generic)
×2
Rotary potentiometer (generic)
Rotary potentiometer (generic)
×2
LF 33 CV
×2
RGB Backlight LCD - 16x2
Adafruit RGB Backlight LCD - 16x2
×1
Switch
×2
Push button
×4
Condensator 10µF
×1

Story

Read more

Schematics

Receiver wiring

TelemetryWiring

Connection between receiver and telemetry module.

Code

Receiver.c

Arduino
Added comments and refactored
//Include 2.4GHz libraries
#include <nRF24L01.h>
#include <RF24.h>
//Servo library
#include <Servo.h>
//Used for I2C communication
#include <Wire.h>

//Set to zero for no debug messages
#define DEBUG 1
#define INITIAL_CHANNEL 0
#define TELEMETRY_CHANNEL 18
#define I2CWAITTIME 1000
//Initialize NRF24
RF24 radio(7, 8); 


Servo channel1;
Servo channel2;
Servo channel3;
Servo channel4;
Servo channel5;
Servo channel6;

Servo servos[6]={};

//NRF24 communication channels 
byte channels[10] = {0};

//NRF24 communication addresses
const byte address[6] = "10001";
const byte senderAddress[6] = "10002";

//Current software version of the receiver
const char versionStr[] = "0.3";


unsigned long i2cTime = 0;
byte i2State = 0;
byte tmChannelCount=0;
String tmChannelNames[10]={};
boolean tmDelivered=false;
boolean radioConnected=false;
boolean namesRequested=false;
unsigned long time;


void setup() {

  //Initialize debug output
  #if DEBUG==1
  Serial.begin(9600);
  #endif
  Wire.begin();
  i2cTime = millis();

  //Connect servos to port
  channel1.attach(2);
  channel2.attach(3);
  channel3.attach(5);
  channel4.attach(6);
  channel5.attach(9);
  channel6.attach(10);

  //Open output for NRF24 status info
  #if DEBUG==1  
  fdevopen( &my_putc, 0);
  #endif
  radio.begin();

  //Initial NRF24 settings
  radio.setRetries(15,15);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_HIGH);
  radio.setChannel(INITIAL_CHANNEL);
  
  radio.openReadingPipe(1, address);
  radio.openWritingPipe(senderAddress);
  radio.startListening();

  //Show connection status
  #if DEBUG==1  
  radio.printDetails();

  if (radio.isChipConnected()) {
    Serial.println("Connected");

  } else {
    Serial.println("Error");
  }
  #endif

}


void loop() {

  //Check I2C every secound
  if (millis() - i2cTime > I2CWAITTIME) {

    //Yet not connected so get information from device
    if (i2State == 0) {
      i2State = requestI2CState();
    //Connection has already been established fetch values
    }else{
      handleChannelValues();
    }
    //increase i2c time
    i2cTime=millis();
  }

  //I2C channel names have been request 
  if(namesRequested){
      handleTMNamesRequest();
  }

  //I2C information has been request by sender
  if(!tmDelivered){
     deliverTelemetry();
  }

  //Radio connection is available
  if (radio.available()) {
    char text[32] = "";
    //Read from radio connection
    radio.read(&text, sizeof(text));
    String received = String(text);


    //Check received command
    //Sender sent ping to check connection
    if (received == "Ping") {
      //Build response Pong + version information
      char commandStr[] = "Pong ";
      char response[sizeof(commandStr) + sizeof(versionStr)] = {0};
      strcpy(response, commandStr);
      strcat(response, versionStr);
      radio.stopListening();
      radio.write(response, sizeof(response));
      #if DEBUG==1
        Serial.println("Sent pong");
      #endif
      delay(5);
      radio.startListening();
      //Connrction has been established
      radioConnected=true;
    } else 
    //Sender requested Telemetry channel info
    if (received.startsWith("CI:")) {
      char *ptr;
      String sChannels = received.substring(4);
      char chaChannels[sChannels.length() + 1];
      sChannels.toCharArray(chaChannels, sChannels.length() + 1);
      ptr = strtok(chaChannels, ";");
      int channelPos = 0;
      while (ptr != NULL) {
        ptr = strtok(NULL, ";");
        String sChannel = ptr;
        int channel = sChannel.toInt();
        if (channelPos < 10) {
          channels[channelPos] = channel;
        }
        channelPos++;
      }
    //Channel position chaned by sender
    } else if (received.startsWith("CH")) {
      String channelStr = received.substring(2, 3);
      String degreeStr = received.substring(3);
      int channel = channelStr.toInt();
      int degree = degreeStr.toInt();
     
      switch (channel) {
        case 1:
          channel1.write(degree);
          break;
        case 2:
          channel2.write(degree);
          break;
        case 3:
          channel3.write(degree);
          Serial.println(received);
          break;
        case 4:
          channel4.write(degree);
          break;
        case 5:
          channel5.write(degree);
          break;
        case 6:
          channel6.write(degree);
          break;
          
      }
    //Telemetry information requested      
    }else if(received.startsWith("TMInfo")){
      tmDelivered=false;
    //Telemetry channel names requested
    }else if(received.startsWith("TMNames")){
      namesRequested=true;
    }
  }
  delay(100);
}


//Used to print NRF24 information
int my_putc( char c, FILE *t) {
  Serial.write( c );
}

//Connect to I2C device and load channel names
int requestI2CState() {
  Wire.beginTransmission(TELEMETRY_CHANNEL);
  //Request data from I2C device
  Wire.write("STATE");
  Wire.endTransmission();
  //Expect maximum of two bytes long answer. 
  Wire.requestFrom(TELEMETRY_CHANNEL, 2);
  char response[2];
  int index = 0;
  boolean found=false;
  while (Wire.available()) {
    found=true;
    char b = Wire.read();
    response[index] = b;
    index++;
  }
  //get number of channels
  String sCount=String(response);
  int count=sCount.toInt();
  if(found){
    tmChannelCount=count;
    tmDelivered=false;
    //Load the names of the channels
    loadChannelNames();
    return 1;
  }else{
    //Something went wrong - no telemtry available
    tmChannelCount=0;
    return 0;
  }
}


//Get the telemetry channel names
void loadChannelNames() {
  //loop through the channels
  //We first need the length of the name
  for(int i=0;i<tmChannelCount;i++){
    Wire.beginTransmission(TELEMETRY_CHANNEL);
    //Prepare command - channel information length
    String string="CHIL"+String(i);

    Wire.write(string.c_str());
    Wire.endTransmission();
    Wire.requestFrom(TELEMETRY_CHANNEL, 2);
    char response[3];
    int index = 0;
    while (Wire.available() && index<2) {
      char b = Wire.read();
      response[index] = b;
      index++;
    }
    response[2]=char(0);
    String sCount=String(response);
    int count=sCount.toInt();
    //Now request the name - channel information
    string="CHI"+String(i);
    Wire.beginTransmission(TELEMETRY_CHANNEL);
    Wire.write(string.c_str());
    Wire.endTransmission();
    //Request chil long name
    Wire.requestFrom(TELEMETRY_CHANNEL, count);
    char nameResponse[count+1];
    index = 0;
    while (Wire.available()) {
      char b = Wire.read();
      nameResponse[index] = b;
      index++;
    }
    nameResponse[count]=char(0);
    String sName=String(nameResponse);
    tmChannelNames[i]=sName;
  }
}


void handleChannelValues(){
  for(int i=0;i<tmChannelCount;i++){
    Wire.beginTransmission(TELEMETRY_CHANNEL);
    String string="CHV"+String(i); 
    Wire.write(string.c_str());
    Wire.endTransmission();
    Wire.requestFrom(TELEMETRY_CHANNEL, 10);
    char response[11];
    int index = 0;
    while (Wire.available() && index<10) {
      char b = Wire.read();
      response[index] = b;
      index++;
    }
    response[10]=char(0);
    String sValue=String(response);
    String commandStr = "TMVALUE "+String(i)+":"+String(sValue.toInt());
    char radioResponse[commandStr.length()+1]={};
    commandStr.toCharArray(radioResponse,commandStr.length()+1);
    radio.stopListening();
    Serial.println(radioResponse);
    radio.write(radioResponse, sizeof(radioResponse));
    Serial.println("Sent value");
    delay(5);
    radio.startListening();
  }
}

void handleTMNamesRequest(){
  namesRequested=false;
      String names="TMNames:";
      for(int i=0;i<tmChannelCount;i++){
        names=names+tmChannelNames[i]+";";
      }
      char response[names.length()+1]={};
      names.toCharArray(response,names.length()+1);
      radio.stopListening();
      if(!radio.write(response, sizeof(response))){
        delay(50);
        radio.write(response, sizeof(response));
      }
      
      Serial.print("Sent names");
      Serial.println(response);
      delay(5);
      radio.startListening();
}

void deliverTelemetry(){
   String commandStr = "TMChannels "+String(tmChannelCount);
      char response[commandStr.length()+1]={};
      commandStr.toCharArray(response,commandStr.length()+1);
      radio.stopListening();
      //radio.write("TMChannels 1",12);
      radio.write(response, sizeof(response));
      delay(5);
      radio.startListening();
      tmDelivered=true;
}

Sender.c

Arduino
Still work in progress
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <EEPROM.h>
#include <Adafruit_ADS1015.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h> 
LiquidCrystal_I2C lcd(0x27, 20, 2); 


#define MAX_STATUS 3
#define MAX_SETTINGS 6
#define MAX_DETAIL_SETTINGS 2
#define TM_STORAGE 25
Adafruit_ADS1115 ads(0x49);
byte antenna[9] = {
  B00000,
  B10001,
  B01110,
  B10101,
  B00100,
  B00100,
  B01010,
  B10001,
  
};

byte battery[8] = {
  0b01110,
  0b11111,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b10001,
  0b11111
};

byte plane[8] = {
  0b00000,
  0b00100,
  0b01100,
  0b01101,
  0b11111,
  0b01101,
  0b01100,
  0b00100,

};

byte telemetry[8] = {
  0b01110,
  0b00100,
  0b11111,
  0b00100,
  0b00000,
  0b11111,
  0b01110,
  0b00100
};
RF24 radio(7, 8); // CE, CSN
const String version="0.2";
const byte address[6] = "10001";
const byte receiveAddress[6] = "10002";
int connectionMode=0;
int detailsSettingsMode=-1;
int viewMode=0;
byte statusMode=0;
int settingsMode=0;
int endPointMode=0;
int centerPointMode=0;
bool reverse[6] ={0};
byte batteryPercent=100;
byte antennaPercent=100;
byte endPointsLeft[6]={90};
byte endPointsRight[6]={90};
byte centerPoints[6]={90};
byte channels[10]={1};
byte throttleMode=0;
byte selectedModel=0;
boolean doRequestTele=false;
boolean buttonReleased=true;
boolean telemetryAvail=false;
boolean telemetryLoaded=false;
String tmChannelNames[10]={""};
int tmChannelValues[10]={0};
unsigned long teleTime=0;
int ip1=0;
int ip2=0;
int ip1Min=0;
int ip2Min=0;
int ip1Max=0;
int ip2Max=0;
boolean repaintStatus=true;
int tempValue;
boolean tmNamesReceived=false;
unsigned long time;
word swTimeSum=0;
unsigned long swTime=0;
boolean swRunning=false;
int physicalEndPoints[6][2]={};
void setup() {
  Serial.begin(9600);
  tone(9, 1500, 100);

  for(int i=0;i<10;i++){
    channels[i]=random(1,11);
  }
  
  if(EEPROM.read(0)!=1){
    EEPROM.update(0,1);
    int position=1;
    for(int i=0;i<6;i++){
      EEPROM.update(position,false);
      position++;
    }
    for(int i=0;i<18;i++){
      EEPROM.update(position,90);
      position++;
    }
    EEPROM.update(position,0);
    position++;
    EEPROM.update(position,0);
    position++;
    
    
  }
  int position=1;
  for(int i=0;i<6;i++){
     reverse[i]=EEPROM.read(position);
     position++;
   }
   for(int i=0;i<6;i++){
     endPointsLeft[i]=EEPROM.read(position);
     position++;
   }
   for(int i=0;i<6;i++){
     endPointsRight[i]=EEPROM.read(position);
     position++;
   }
   for(int i=0;i<6;i++){
     centerPoints[i]=EEPROM.read(position);
     position++;
   }
  throttleMode=EEPROM.read(position);
  position++;
  Serial.print("Selected model ");
  selectedModel=EEPROM.read(position);
  Serial.println(selectedModel);
  position++;
  lcd.init(); //Im Setup wird der LCD gestartet 
  lcd.createChar(0, antenna);
  lcd.createChar(1, battery);
  lcd.createChar(2, plane);
  lcd.createChar(3, telemetry);
  
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Transmitter "+version);
  lcd.setCursor(0,1);
  lcd.print("Initializing...");
  radio.begin();
  //radio.enableAckPayload();
  //radio.setDataRate(RF24_1MBPS);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_HIGH);
  radio.setRetries(15,15);
  radio.setChannel(0);
  radio.openWritingPipe(address);
  radio.openReadingPipe(1,receiveAddress);
  //radio.enableAckPayload();
  //radio.stopListening();
  
  fdevopen( &my_putc, 0);
  radio.printDetails();
  if(radio.isChipConnected()){
    lcd.setCursor(0,1);
    lcd.print("Online/Pairing ");
    
    connectionMode=1;
    
  }else{
    lcd.setCursor(0,1);
    lcd.print("Connection error");
  }
}

int channel1 = A0;
int channel2 = A1;
int channel3 = A2;
int channel4 = A3;

int channelValues[6]={0};
boolean channelSelect=false;
int selectedChannel=0;
int key=-1;
int keyPressed=-1;
int keyTime=0;
int keyWait=0;
void loop() {

  
  
  if(millis()-keyWait>100){
    keyWait=millis();
  int in3=digitalRead(3);
  int in4=digitalRead(4);
  int in5=digitalRead(5);
  int in6=digitalRead(6);  
  if(in3==LOW && in4==LOW && in5==LOW && in6==LOW && !buttonReleased){

    
    if(millis()-keyTime>200){
      keyPressed=key;
    }
    
    buttonReleased=true;
    keyTime=0;
    key=-1;
    delay(100);
    
  }else

  Serial.println(String(in3)+" "+String(millis()-keyTime>4000)+" "+String(viewMode)+" "+String(keyTime));
  if(in3==HIGH && key==0 && millis()-keyTime>4000 && viewMode==1 && keyTime>0){
    if(buttonReleased){
      keyTime=millis();
      buttonReleased=false;
    }else{
      keyPressed=4;
      key=-1;
      keyTime=0;
      Serial.println("Long pressed");
      Serial.println("Key 3");
    }

    
  }else
  if(in3==HIGH && key==-1 && keyTime==0 && buttonReleased){
    key=0;
    keyTime=millis();
    buttonReleased=false;
    
  }else
   if(in4==HIGH && key==-1 && keyTime==0 && buttonReleased){
    key=1;
    keyTime=millis();
    Serial.println("Key 4");
    buttonReleased=false;
    
  }else
    if(in5==HIGH && key==-1 && keyTime==0 && buttonReleased){
    key=2;
    keyTime=millis();
    Serial.println("5 high");
    buttonReleased=false;
    
  }else
    if(in6==HIGH && key==-1 && keyTime==0 && buttonReleased){
    key=3;
    keyTime=millis();
    Serial.println("6 high");
    buttonReleased=false;
    
  }
  }
  
  if(keyPressed>-1 || Serial.available()){
    Serial.println("Keypressed "+String(keyPressed));
    char chr;
    if(keyPressed>-1){
      switch(keyPressed){
        case 4:
        chr='a';
        break;
        case 0:
        chr='g';
        break;
        case 1:
        chr='s';
        break;
        case 2:
        chr='d';
        break;
        case 3:
        chr='f';
        break;
        
      }
      keyPressed=-1;
    }else{
      chr=Serial.read();
    }
    
    //Simulate long enter
    //Serial.println("Char "+chr);
    if(chr=='a' && viewMode==1){
      tone(9, 1000, 100);

      viewMode=2;
      settingsMode=0;
      detailsSettingsMode=-1;
      showSettingsView();
    }else
    //Simulate back 
    if(chr=='s' && viewMode==2 && !channelSelect && (settingsMode!=5 || (settingsMode==5 && detailsSettingsMode==-1))){
      tone(9, 1000, 100);
      viewMode=1;
      showStatusView();
    }else
    if(chr=='s' && viewMode==2 && settingsMode==5 && detailsSettingsMode>-1){
      detailsSettingsMode=-1;
      showSettingsView();
      lcd.noBlink();
    }else
    if(chr=='s' && viewMode==2 && settingsMode==2 && centerPointMode==1){
      centerPointMode=0;
      paintCenterPoints();
      lcd.setCursor(9+selectedChannel,0);
    }else
    //Exit channel select
    if(chr=='s' && viewMode==2 && (settingsMode!=1 || endPointMode==0)){
      channelSelect=false;
      lcd.noBlink();
    }else
    //SW reset
    if(chr=='s' && viewMode==1 && statusMode==1){

      swRunning=false;
      swTimeSum=0;
      showStatusView();
       
       
    }else
    //Exit endpoint
    if(chr=='s' && viewMode==2 && settingsMode==1 && endPointMode!=0){
       channelSelect=true;
       endPointMode=0;
       lcd.setCursor(0,1);
       lcd.print("     ");
       lcd.setCursor(13,1);
       lcd.print("    ");
       lcd.setCursor(9+selectedChannel,0);
    }else
    //Simulate left
    //Change detail settings
    if(chr=='d' && viewMode==2 && settingsMode==5 && detailsSettingsMode>0){
      detailsSettingsMode--;
      showSettingsView();
      
    }else
    //Change status view down
    if(chr=='d' && viewMode==1 && statusMode>0){
      statusMode--;
      showStatusView();
    }else
    if(chr=='d' && viewMode==2 && !channelSelect){
      if(settingsMode>0){
        settingsMode--;
      }
      showSettingsView();
    }else
    //Decrease selected channel
    if(chr=='d' && viewMode==2 && channelSelect  && (settingsMode!=1 || endPointMode==0)  && (settingsMode!=2 || centerPointMode==0)){
      if(selectedChannel>0){
        selectedChannel--;
      }
      if(settingsMode==1){
        lcd.setCursor(0,1);
        lcd.print("-   ");
        lcd.setCursor(1,1);
        lcd.print(endPointsLeft[selectedChannel]);
        lcd.setCursor(13,1);
        lcd.print("   ");
        lcd.setCursor(13,1);
        lcd.print(endPointsRight[selectedChannel]);
        
      }else
      if(settingsMode==2){
        paintCenterPoints();

        
      }
      lcd.setCursor(9+selectedChannel,0);
    }else
    //Decrease centerpoint left
    if(chr=='d' && viewMode==2 && settingsMode==2 && centerPointMode==1){
      Serial.println("Decrease left endpoint");
      if(tempValue-5>=0){
        paintCenterPoints();
        
      }
      
    }else  
    //Increase endpoint left
    if(chr=='d' && viewMode==2 && settingsMode==1 && endPointMode==1){
      Serial.println("Increase right endpoint");
      if(endPointsLeft[selectedChannel]+5<=90){
        endPointsLeft[selectedChannel]=endPointsLeft[selectedChannel]+5;
        lcd.setCursor(0,1);
        lcd.print("-   ");
        lcd.setCursor(1,1);
        lcd.print(endPointsLeft[selectedChannel]);
        lcd.setCursor(0,1);
        
      }
      
    }else  
    //Decrease endpoint right  
    if(chr=='d' && viewMode==2 && settingsMode==1 && endPointMode==2){
      Serial.println("Decrease right endpoint");
      if(endPointsRight[selectedChannel]-5>=0){
        endPointsRight[selectedChannel]=endPointsRight[selectedChannel]-5;
        lcd.setCursor(13,1);
        lcd.print("   ");
        lcd.setCursor(13,1);
        lcd.print(endPointsRight[selectedChannel]);
        lcd.setCursor(13,1);
        
      }
      
    }else  
        //Simulate right
        //Change detail settings
    if(chr=='f' && viewMode==2 && settingsMode==5 && detailsSettingsMode>-1){
      if(detailsSettingsMode<MAX_DETAIL_SETTINGS){
        detailsSettingsMode++;
        showSettingsView();
        //showStatusView();
      }
    }else
    if(chr=='f' && viewMode==1 && statusMode<MAX_STATUS){
      statusMode++;
      showStatusView();
    }
    if(chr=='f' && viewMode==2 && !channelSelect && (settingsMode!=5 || detailsSettingsMode==-1)){
      if(settingsMode<MAX_SETTINGS){
        settingsMode++;
      }
      showSettingsView();
    }else
    //Step to next channel 
    if(chr=='f' && viewMode==2 && channelSelect && (settingsMode!=1 || endPointMode==0)  && (settingsMode!=2 || centerPointMode==0)){
      Serial.println("Next channel");
      if(selectedChannel<5){
        selectedChannel++;
      }
      if(settingsMode==1){
        lcd.setCursor(0,1);
        lcd.print("-   ");
        lcd.setCursor(1,1);
        lcd.print(endPointsLeft[selectedChannel]);
        lcd.setCursor(13,1);
        lcd.print("   ");
        lcd.setCursor(13,1);
        lcd.print(endPointsRight[selectedChannel]);
        
      }else
      if(settingsMode==2){
        paintCenterPoints();

        
      }
      lcd.setCursor(9+selectedChannel,0);
    }else
    //Decrease centerpoint left
    if(chr=='f' && viewMode==2 && settingsMode==2 && centerPointMode==1){
      Serial.println("Decrease left endpoint");
      if(tempValue+5<=180){
        tempValue=tempValue+5;
        paintCenterPoints();
        
      }
      
    }else  
    //Decrease endpoint left
    if(chr=='f' && viewMode==2 && settingsMode==1 && endPointMode==1){
      Serial.println("Decrease left endpoint");
      if(endPointsLeft[selectedChannel]-5>=0){
        endPointsLeft[selectedChannel]=endPointsLeft[selectedChannel]-5;
        lcd.setCursor(0,1);
        lcd.print("-   ");
        lcd.setCursor(1,1);
        lcd.print(endPointsLeft[selectedChannel]);
        lcd.setCursor(0,1);
        
      }
      
    }else  
    //Increase endpoint right  
    if(chr=='f' && viewMode==2 && settingsMode==1 && endPointMode==2){
      Serial.println("Increase right endpoint");
      if(endPointsRight[selectedChannel]+5<=90){
        endPointsRight[selectedChannel]=endPointsRight[selectedChannel]+5;
        lcd.setCursor(13,1);
        lcd.print("   ");
        lcd.setCursor(13,1);
        lcd.print(endPointsRight[selectedChannel]);
        lcd.setCursor(13,1);
        
      }
      
    }else  
    //Simulate enter
    
    //Detail setingsmode enter
    if(chr=='g' && viewMode==2 && !channelSelect && settingsMode==5){
      switch(detailsSettingsMode){
        case -1:
          detailsSettingsMode=0;
          showSettingsView();
          lcd.setCursor(0,1);
          lcd.blink();
          break;
        case 0:
          if(throttleMode==0){
            throttleMode=1;
          }else{
            throttleMode=0;
          }
          EEPROM.update(TM_STORAGE,throttleMode);
          showSettingsView();
      }

      
    }else
    //Channel selection part
    if(chr=='g' && viewMode==2 && !channelSelect && (settingsMode==0 || settingsMode==1 || settingsMode==2 || settingsMode==4)){
       channelSelect=true;
       selectedChannel=0;

       if(settingsMode==1){
        lcd.setCursor(0,1);
        lcd.print("-   ");
        lcd.setCursor(1,1);
        lcd.print(endPointsLeft[selectedChannel]);
        lcd.setCursor(13,1);
        lcd.print("   ");
        lcd.setCursor(13,1);
        lcd.print(endPointsRight[selectedChannel]);
        lcd.setCursor(9,0);

      }else
      if(settingsMode==2){
        paintCenterPoints();
        lcd.setCursor(9,0);

        
      }
      lcd.setCursor(9,0);
      endPointMode=0; 
      lcd.blink();
      
    }else
    //Reverse enter
    if(chr=='g' && viewMode==2 && channelSelect && settingsMode==0){
       channelSelect=true;
       reverse[selectedChannel]=!reverse[selectedChannel];
        lcd.setCursor(9+selectedChannel,1);
        if(reverse[selectedChannel]){
          lcd.print("R");
 
       }else{
        lcd.print(" ");
       }
       saveReverse();
       setChannelValue(selectedChannel,channelValues[selectedChannel]);
       lcd.setCursor(9+selectedChannel,0);
       
    }else

    //SW start enter
    if(chr=='g' && viewMode==1 && statusMode==1){

      swRunning=!swRunning;
      if(swRunning){
       swTime=millis();
      }
       
       
    }else
    //Centerpoint enter
    if(chr=='g' && viewMode==2 && channelSelect && settingsMode==2 && centerPointMode==0){
       tempValue=centerPoints[selectedChannel];
       channelSelect=true;
       centerPointMode=1;
       paintCenterPoints();
       
       
    }else
    //Centerpoint finish
    if(chr=='g' && viewMode==2 && channelSelect && settingsMode==2 && centerPointMode==1){
       centerPoints[selectedChannel]=tempValue;
       channelSelect=true;
       centerPointMode=0;
       paintCenterPoints();
       saveCenterPoints();
       lcd.setCursor(9+selectedChannel,0);
    }else
    //Endpoint enter
    if(chr=='g' && viewMode==2 && channelSelect && settingsMode==1 && endPointMode==0){
       channelSelect=true;
       endPointMode=1;
       lcd.setCursor(0,1);
       lcd.print("-   ");
       lcd.setCursor(1,1);
       lcd.print(endPointsLeft[selectedChannel]);
       lcd.setCursor(13,1);
       lcd.print("  ");
       lcd.setCursor(13,1);
       lcd.print(endPointsRight[selectedChannel]);
       
       lcd.setCursor(0,1);
       
    }else
    //Endpoint right selection
    if(chr=='g' && viewMode==2 && channelSelect && settingsMode==1 && endPointMode==1){
       channelSelect=true;
       endPointMode=2;
       lcd.setCursor(0,1);
       lcd.print("-    ");
       lcd.setCursor(1,1);
       lcd.print(endPointsLeft[selectedChannel]);
       lcd.setCursor(13,1);
       lcd.print("   ");
       lcd.setCursor(13,1);
       lcd.print(endPointsRight[selectedChannel]);
       
       lcd.setCursor(13,1);
       
    }else
    //Finish endpoint
    if(chr=='g' && viewMode==2 && channelSelect && settingsMode==1 && endPointMode==2){
       channelSelect=true;
       endPointMode=0;
       lcd.setCursor(0,1);
       lcd.print("     ");
       lcd.setCursor(13,1);
       lcd.print("    ");
       lcd.setCursor(9+selectedChannel,0);
       saveEndPointsLeft();
       saveEndPointsRight();
    }
    
  }

  //Read input 
  int val;
  val = analogRead(channel1); 
  if(abs(val-channelValues[0])>0 && connectionMode==2){
    //Serial.print(val);
    setChannelValue(0,val);
    channelValues[0]=val;
  }
  val = analogRead(channel2); 
  if(abs(val-channelValues[1])>0 && connectionMode==2){
    //Serial.print(val);
    setChannelValue(1,val);
    channelValues[1]=val;
  }
  val = analogRead(channel3); 
  if(abs(val-channelValues[2])>0 && connectionMode==2){
    //Serial.print(val);
    setChannelValue(2,val);
    channelValues[2]=val;
  }
  val = analogRead(channel4); 
  if(abs(val-channelValues[3])>0 && connectionMode==2){
    //Serial.print(val);
    setChannelValue(3,val);
    channelValues[3]=val;
  }
  val = ads.readADC_SingleEnded(0);
  if(abs(val-channelValues[4])>0 && connectionMode==2){
    setChannelValue(4,val);
    channelValues[4]=val;
  }
  val = ads.readADC_SingleEnded(1);
  if(abs(val-channelValues[5])>0 && connectionMode==2){
    setChannelValue(5,val);
    channelValues[5]=val;
  }

  
  //sendMessage(text);

  if(doRequestTele){
    doRequestTele=false;
    requestTelemetry();
  }


  if(connectionMode==1){
    if(millis()-time>500){
      char text[] = "Ping";
      radio.stopListening();
      bool rslt;
      radio.write(text, sizeof(text)); 
      Serial.println("Writing ping");
      time=millis();
      delay(5);
      radio.startListening();
    }
  }
  
  if(connectionMode>0){  
    if(telemetryLoaded && !tmNamesReceived && millis()-teleTime>1000){
        radio.stopListening();
        
        radio.write("TMNames",7); 
        Serial.println("Requesting channel names");
        delay(5);
        radio.startListening();
        teleTime=millis();
    }
    if(!telemetryLoaded && millis()-teleTime>1000){
      teleTime=millis();
      requestTelemetry();
    }
    //radio.startListening();
    if (radio.available()) {
      char text[32] = "";
      radio.read(&text, sizeof(text));
      String received=String(text);
      if(received.startsWith("Pong")){
        lcd.setCursor(0,1);
        lcd.print("Paired. "+received.substring(5)+"   ");
        tone(9, 1800, 100);
        delay(100);
        tone(9, 1800, 100);
        
        viewMode=1;
        connectionMode=2;        
        time=millis();
        delay(100);
        sendChannels();
        doRequestTele=true;
        
      }else
      if(received.startsWith("TMChannels ")){
        telemetryLoaded=true;
        Serial.println(received); 
        String sChannels=received.substring(11);
        int lChannels=sChannels.toInt();
        Serial.println(sChannels+"#"+String(lChannels));
        telemetryAvail=lChannels>0;
        if(viewMode==1 && statusMode==0){
          showStatusView();
          
          
        }
        
        radio.stopListening();
        
        radio.write("TMNames",7); 
        Serial.println("Requesting channel names");
        delay(5);
        radio.startListening();
      }else
      if(received.startsWith("TMVALUE ")){
        Serial.println("Got value: "+received.substring(8));
        String sChannel=received.substring(8,received.indexOf(":"));
        String sValue=received.substring(received.indexOf(":",8)+1);
        
        tmChannelValues[sChannel.toInt()]=sValue.toInt();
        if(viewMode==1 && statusMode==2){
          showStatusView();
        }
        Serial.println("Channel: "+sChannel+" "+sValue);
      }else
      if(received.startsWith("TMNames:")){
        tmNamesReceived=true;
        Serial.println("Got names: "+received);
        char *ptr;
        String sChannelNames = received.substring(8);
        Serial.println("SChannelNames: "+sChannelNames);
        char chaChannelNames[sChannelNames.length() + 1];
        sChannelNames.toCharArray(chaChannelNames, sChannelNames.length() + 1);
        ptr = strtok(chaChannelNames, ";");
        int channelPos = 0;
        while (ptr != NULL) {
          String sChannelName = ptr;
          
          Serial.println(sChannelName);
          if (channelPos < 10) {
            tmChannelNames[channelPos] = sChannelName;
          }
          ptr = strtok(NULL, ";");

          channelPos++;
        }
        if(viewMode==1 && statusMode==2){
          showStatusView();
        }
      }
      Serial.println(received);
      //Serial.print("Txt ");
      //Serial.println(text);
    }
  
  
  }
  if(viewMode==1 && swRunning && statusMode==1 && millis()-time>1000){
    showStatusView();
    time=millis();
    repaintStatus=false;
  }else
  if(viewMode==1 && millis()-time>4000 && repaintStatus){
    showStatusView();
    time=millis();
    repaintStatus=false;

    
  }
}

void showStatusView(){
  lcd.clear();
  switch(statusMode){
    case 0:
      lcd.setCursor(0,0);
      
      lcd.write(byte(1));
      lcd.print(" ");
      lcd.print(batteryPercent);
      lcd.print("%");
      lcd.setCursor(0,1);
      lcd.write(byte(0));
      lcd.print(" ");
      lcd.print(antennaPercent);
      lcd.print("%");
      lcd.setCursor(7,0);
      lcd.write(byte(2));
      lcd.print(" ");

      if(selectedModel==0){
        lcd.print("not sel");
      }else{
        lcd.print(selectedModel);  
      }
      
      lcd.setCursor(7,1);
      lcd.write(byte(3));
      if(telemetryAvail){
        lcd.print(" ok");   
      }else{
        lcd.print(" no cnct"); 
      }
           
      break;
    case 1:
      lcd.setCursor(0,0);
      if(swTime==0){
        lcd.print("Stopwatch: 00:00");
      }else{
        if(swRunning){
          unsigned long currentTime=millis();
          swTimeSum=swTimeSum+(currentTime-swTime)/1000;
          swTime=millis();
        }
        
        lcd.print("Stopwatch: ");  
        word minutes=(word)((unsigned long)(swTimeSum)/(unsigned long)(60UL));
        Serial.print(minutes);
        Serial.println();
        if(minutes<10){
          lcd.print("0");
        }
        lcd.print(minutes);
        lcd.print(":");
        word seconds=(swTimeSum-(minutes*60UL));
        if(seconds<10){
          lcd.print("0");
        }
        lcd.print(seconds);
      }
      lcd.setCursor(0,1);
      lcd.print("Engine     00:00");
      break;
    case 2:
      if(telemetryAvail){
      lcd.setCursor(0,0);
      lcd.print(tmChannelNames[0]+": "+String(tmChannelValues[0]));

      lcd.setCursor(0,1);
      lcd.print(tmChannelNames[1]+": "+String(tmChannelValues[1]));

      }else{
        lcd.setCursor(0,0);
        lcd.print("No telemetry");
      }
      break;
    case 3:
      lcd.setCursor(0,0);
      lcd.print("1:");
      lcd.print(getDegree(0,channelValues[0]));
      lcd.setCursor(5,0);
      lcd.print("2:");
      lcd.print(getDegree(1,channelValues[1]));
      lcd.setCursor(11,0);
      lcd.print("3:");
      lcd.print(getDegree(2,channelValues[2]));
      lcd.setCursor(0,1);
      lcd.print("4:");
      lcd.print(getDegree(3,channelValues[3]));
       lcd.setCursor(5,1);
      lcd.print("5:");
      lcd.print(getDegree(4,channelValues[4]));
       lcd.setCursor(11,1);
      lcd.print("6:");
      lcd.print(getDegree(5,channelValues[5]));
      
    break;
  }

}

void showSettingsView(){
  lcd.clear();
  switch(settingsMode){
    case 0:
        lcd.setCursor(0,0);
        lcd.print("Reverse");
        lcd.setCursor(9,0);
        lcd.print("123456");
        for(int i=0;i<6;i++){
          lcd.setCursor(9+i,1);
          if(reverse[i]){
            lcd.print("R");  
          }else{
            lcd.print(" ");
          }
        }
        break;
    case 1:
        lcd.setCursor(0,0);
        lcd.print("Endpoint");
        lcd.setCursor(9,0);
        lcd.print("123456");

        
        break;

    case 2:
        lcd.setCursor(0,0);
        lcd.print("Trim");

        lcd.setCursor(9,0);
        lcd.print("123456");
        break;
    case 3:
        lcd.setCursor(0,0);
        lcd.print("Mix");
        lcd.setCursor(0,1);
        lcd.print("Flaperon (OFF)");
        break;
    case 4:
        lcd.setCursor(0,0);
        lcd.print("Channels");
        lcd.setCursor(9,0);
        lcd.print("123456");
        break;  
    case 5:
        lcd.setCursor(0,0);
        lcd.print("Settings");
        lcd.setCursor(0,1);
        switch(detailsSettingsMode){
          case 0:
              
              if(throttleMode==0){
                lcd.print("Throttle: Left");
              }else{
                lcd.print("Throttle: Right");
                
              }
              break;
           case 1:
              lcd.print("Calibrate");
              break;
        }

      
        break;  
     case 6:
        lcd.setCursor(0,0);
        lcd.print("Models");
        lcd.setCursor(7,0);
        lcd.print("Load/Save");
        break;  
  }

}

int my_putc( char c, FILE *t) {
  Serial.write( c );
}


void paintCenterPoints(){
  lcd.setCursor(0,1);
...

This file has been truncated, please download it to see its full contents.

TelemetrySender

Arduino
Only transmitting random values for testing
Still work in progress
#include <Wire.h>
#define PROTOCOL_VERSION 1
//Number of input channels
const byte channelCount=2;

//State channel names here
String channels[2]={"TestChannel1","Test2"};
int channelValues[2]={0};

void setup() {
  Wire.begin(18);
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
  Serial.println("Started");
  setupSensors();
  Serial.println("Sensors initialized");
  
}

void loop() {
  //Just dummy values. Retreive data from sensors here
  channelValues[0]=random(1,1000);
  channelValues[1]=random(1,3000);
  delay(1000);
}

//Command sent by receiver (1: STATE, 2: CHIL, 3: CHI, 4: CHV, 5: INF
byte commandCode=0;
byte channel=0;
void receiveEvent(int howMany) {
    String command="";
    while (0 < Wire.available()) {
        char x = Wire.read();

        
        command.concat(String(x));
    }
    //Receiver requests number of input channels
    if(command=="STATE"){
      commandCode=1;
    }else
    //Receiver requests length of channel name
    //This intermediate step is neccessary as I2C communication needs a defined length to listen to
    if(command.startsWith("CHIL")){
      commandCode=2;
      channel=extractChannel("CHIL",command);
      
    }else
    //Receiver requests the name of a channel
    if(command.startsWith("CHI")){
      commandCode=3;
      channel=extractChannel("CHI",command);
     
    }else
    if(command.startsWith("CHV")){
      commandCode=4;
      channel=extractChannel("CHV",command);
      
    }else
    if(command=="INF"){
      commandCode=5;
    }
    
    
    Serial.println("Command received "+command);

}

  
void requestEvent() {
  if(commandCode>0){
    String toSend="";
    switch(commandCode){
      
      case 1:
      if(channelCount<10){
        toSend="0";
        toSend.concat(String(channelCount));
      }else{
        toSend=String(channelCount);
      }
        break;
      case 2:{
        int cLen=channels[channel].length();
        if(cLen<10){
          toSend="0";
          toSend.concat(String(cLen));
        }else{
          toSend=String(cLen);
        }
      }
        break;
      case 3:
        toSend=String(channels[channel]);
        break;
      case 4:
        toSend=getChannelValue(channel);
        break;
      case 5:{
        String sVersion=String(PROTOCOL_VERSION);
        while(sVersion.length()<3){
          sVersion="0"+sVersion;
        }
        toSend=sVersion;}
        break;  
      default:
        toSend="ER";
    }
    Serial.println("To send: "+toSend);
    char buffer[toSend.length()+1];
    toSend.toCharArray(buffer, toSend.length()+1);
    Wire.write(buffer);
    //Command has been handled set to 0
    commandCode=0;
  }
}

int extractChannel(String command,String request){
  String sChannel=request.substring(command.length());
  Serial.println("SC "+sChannel);
  return sChannel.toInt();
}

String getChannelValue(int channel){
  int value=channelValues[channel];
  String sValue=String(value);
  while(sValue.length()<10){
    sValue="0"+sValue;
   }
   return sValue;
}

void setupSensors(){
  //Setting up sensors goes here
}

Credits

Nico Hennrich

Nico Hennrich

1 project • 0 followers

Comments