New here and immediately asking for help

This is only part of forum, that is closest to my problem where i can post.
I'm new to Arduino or C++, but still managed to get my project started.
I'm building prototype for tank(alike, nothing like that actually). chassis is driven by motors, which are controlled by relays (no variable speed needed) and 6 channel RC-Controller controlling everything. There is allso option to flip switch on controller to put this device to follow line taped to floor. Steering is working and switch is reading properly on serial monitor. I have minor difficulties to get FAILSAFE working and creating "subrutine" to be activated via switch. I think that FAILSAFE should be own "rutine" and Line following allso. So any thoughts or suggestions how to build code?

THX For replays.

Ville
Finland

#include <EnableInterrupt.h>

//Serial nopeus ja kanavamäärä
#define SERIAL_PORT_SPEED 9600
#define RC_NUM_CHANNELS 4

//KanavaNimet
#define RC_CH1 0
#define RC_CH2 1
#define RC_CH3 2
#define RC_CH4 3

//KanavaInputit
#define RC_CH1_INPUT A0
#define RC_CH2_INPUT A1
#define RC_CH3_INPUT A2
#define RC_CH4_INPUT A3



//Keskeytykset
uint16_t rc_values[RC_NUM_CHANNELS];
uint32_t rc_start[RC_NUM_CHANNELS];
volatile uint16_t rc_shared[RC_NUM_CHANNELS];

void rc_read_values() {
 noInterrupts();
 memcpy(rc_values, (const void *)rc_shared, sizeof(rc_shared));
 interrupts();
}

void calc_input(uint8_t channel, uint8_t input_pin) {
 if (digitalRead(input_pin) == HIGH) {
   rc_start[channel] = micros();
 } else {
   uint16_t rc_compare = (uint16_t)(micros() - rc_start[channel]);
   rc_shared[channel] = rc_compare;
 }
}

void calc_ch1() {
 calc_input(RC_CH1, RC_CH1_INPUT);
}
void calc_ch2() {
 calc_input(RC_CH2, RC_CH2_INPUT);
}
void calc_ch3() {
 calc_input(RC_CH3, RC_CH3_INPUT);
}
void calc_ch4() {
 calc_input(RC_CH4, RC_CH4_INPUT);
}

void setup() {
 Serial.begin(SERIAL_PORT_SPEED);
 //pinMode(2, INPUT);
 //pinMode(3, INPUT);
 pinMode(RC_CH1_INPUT, INPUT);
 pinMode(RC_CH2_INPUT, INPUT);
 pinMode(RC_CH3_INPUT, INPUT);
 pinMode(RC_CH4_INPUT, INPUT);
 pinMode(13, OUTPUT);
 pinMode(12, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(10, OUTPUT);
 pinMode(9, OUTPUT);

 //Ulostulot pois päältä käynnistyksessä
 digitalWrite(13, LOW);
 digitalWrite(12, HIGH);
 digitalWrite(11, HIGH);
 digitalWrite(10, HIGH);
 digitalWrite(9, HIGH);



 enableInterrupt(RC_CH1_INPUT, calc_ch1, CHANGE);
 enableInterrupt(RC_CH2_INPUT, calc_ch2, CHANGE);
 enableInterrupt(RC_CH3_INPUT, calc_ch3, CHANGE);
 enableInterrupt(RC_CH4_INPUT, calc_ch4, CHANGE);
}

void loop() {
 rc_read_values();
 Serial.print("CH1:");
 Serial.print(rc_values[RC_CH1]);
 Serial.print("\t");
 Serial.print("CH2:");
 Serial.print(rc_values[RC_CH2]);
 Serial.print("\t");
 Serial.print("CH3:");
 Serial.print(rc_values[RC_CH3]);
 Serial.print("\t");
 Serial.print("CH4:");
 Serial.println(rc_values[RC_CH4]);
 delay(200);





 //Vedellään Releitä
 if (rc_values[RC_CH1] < 1600) {
   digitalWrite(9, HIGH);
 } else digitalWrite(9, LOW);

 if (rc_values[RC_CH1] > 1450) {
   digitalWrite(10, HIGH);
 } else digitalWrite(10, LOW);

 if (rc_values[RC_CH2] > 1450) {
   digitalWrite(11, HIGH);
 } else digitalWrite(11, LOW);

 if (rc_values[RC_CH2] < 1600) {
   digitalWrite(12, HIGH);
 } else digitalWrite(12, LOW);

 //Lisäkanava kytkimellä(n.1100-1900)
 if (rc_values[RC_CH3] > 1500) {
   digitalWrite(13, HIGH);
 } else digitalWrite(13, LOW);


 //FAILSAFE
 if (rc_values[RC_CH4] < 1800) {
   digitalWrite(13, LOW);
   digitalWrite(12, HIGH);
   digitalWrite(11, HIGH);
   digitalWrite(10, HIGH);
   digitalWrite(9, HIGH);
 }
}
digitalWrite(9, rc_values[RC_CH1] < 1600);

That is correct. That part and everything ecxept FAILSAFE part is working just fine. Program is so slow, that FAILSAFE is trying to pull relays, relay indicaotr LED is barely flashing, but there isn enough time to gather current to pull relay itself, so in theory its working, but it's still wrong.

What did you mean by posting that part of code?
Or is that just more correct/easyer way of writing it?
I'm NOOB try to understand...

THX.

if i understand you correct, FAILSAFE in this case means a mode in which the RemoteControl should be ignored and some sensors giving position of black tape under the vehicle and their state should be converted into relay control.

FAILSAFE is situation when signal is lost totally. then all relays should release, and model should stop. Ideal situation would be to get FollowLine funktion to work when CH3 switch is on. So you could first drive and maneuver model to line, turn switch, and model should follow line with supervision of operator. This machine is allmost like pumptrolley for handling pallets. So trolley could travel easier floors with linefollow mode, and when parking or when some other traffic issues occur, human would turn switch and continue controlling.

I think i can and i want to try to make code for linefollowing, but i dont know how to call that program with switch. I tested it once, but i did'nt put interruptions there so it didnt work. INPUT got stuck, when both sensors were on top of the tape, when tape was removed, other sensor was still pulled, so program stopped reading both sensors.

THX Again.

how arduino will know that RC receiver has lost the connection?

Channel CH4 is throttle on transmitter, which is pulled down when receiver loses signal.
It is builtin function on transmitter for not losing your RC-Plane, or Boat, or whatever model you are controlling.

normally it over 1800 ? right?

#include <EnableInterrupt.h>

//Serial nopeus ja kanavamäärä
#define SERIAL_PORT_SPEED 9600
#define RC_NUM_CHANNELS 4

//KanavaNimet
#define RC_CH1 0
#define RC_CH2 1
#define RC_CH3 2
#define RC_CH4 3

//KanavaInputit
#define RC_CH1_INPUT A0
#define RC_CH2_INPUT A1
#define RC_CH3_INPUT A2
#define RC_CH4_INPUT A3



//Keskeytykset
uint16_t rc_values[RC_NUM_CHANNELS];
uint32_t rc_start[RC_NUM_CHANNELS];
volatile uint16_t rc_shared[RC_NUM_CHANNELS];

void rc_read_values() {
  noInterrupts();
  memcpy(rc_values, (const void *)rc_shared, sizeof(rc_shared));
  interrupts();
}

void calc_input(uint8_t channel, uint8_t input_pin) {
  if (digitalRead(input_pin))     rc_start[channel] = micros();
   else     rc_shared[channel] =  (uint16_t)(micros() - rc_start[channel]);
}

void calc_ch1() {
  calc_input(RC_CH1, RC_CH1_INPUT);
}
void calc_ch2() {
  calc_input(RC_CH2, RC_CH2_INPUT);
}
void calc_ch3() {
  calc_input(RC_CH3, RC_CH3_INPUT);
}
void calc_ch4() {
  calc_input(RC_CH4, RC_CH4_INPUT);
}

void setup() {
  Serial.begin(SERIAL_PORT_SPEED);
  //pinMode(2, INPUT);
  //pinMode(3, INPUT);
  pinMode(RC_CH1_INPUT, INPUT);
  pinMode(RC_CH2_INPUT, INPUT);
  pinMode(RC_CH3_INPUT, INPUT);
  pinMode(RC_CH4_INPUT, INPUT);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(9, OUTPUT);

  initState();

  enableInterrupt(RC_CH1_INPUT, calc_ch1, CHANGE);
  enableInterrupt(RC_CH2_INPUT, calc_ch2, CHANGE);
  enableInterrupt(RC_CH3_INPUT, calc_ch3, CHANGE);
  enableInterrupt(RC_CH4_INPUT, calc_ch4, CHANGE);
}

void loop() {
  rc_read_values();

  if (rc_values[RC_CH4] < 1500) initState();  //FAILSAFE
  else  {
    digitalWrite(9, rc_values[RC_CH1] < 1600);    //Vedellään Releitä
    digitalWrite(10, rc_values[RC_CH1] > 1450);
    digitalWrite(11, rc_values[RC_CH2] > 1450);
    digitalWrite(12, rc_values[RC_CH2] < 1600);
    digitalWrite(13, rc_values[RC_CH3] > 1500);  //Lisäkanava kytkimellä(n.1100-1900)
  }
}

void initState() { //Ulostulot pois päältä käynnistyksessä
  digitalWrite(13, LOW);
  digitalWrite(12, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(9, HIGH);
}

Signal variation is About 1200-1900, so i put value 1800, so i is almost at full throttle(stick up) when model is operetable. Same with switch for CH3, it is allso about 1200-1900, so 1500 is fine.

lataus

I know the Spektrum DXi6 pretty well. You could setup the motor-throttle cut-switch to a certain value to run/stop the motor
If the motor-cut switch is activated the throttle-channel stays on the signal for "CUT-OFF" regardless what position the throttle-stick has.

Model control is done by right stick, like panzerwagen type steering. Throttle is not being used and because receiver that im using has FAILSAFE only in throttle, it needs to be done in arduino program. And reading throttle in arduino works well enough. Throttle is not used, because there is no need for speedcontrol and spring centering stick is at right side. Just push stick all the way up, both motors run, at 2'o clock position only left motor runs, at 3'O clock other motor turns clockwise and other CCW and so on.

THX

Connection to motor is like this, and analogs are connected to receiver. There are not "linefollowingsensors" on the picture. Those should be added still.

ps.there is 2 grounds missing from two relays, it's working system from that aspect anyways...

does Uno work with 4 interrupts?

Yes. Every pin has atleast CHANGE interrupt and PINs 2-3 has hardware interrupts. All RC controls are going through interrupt and pins 2-3 are both free to use for whatever.

this sort of interrupt fires by change of any pin on this port and user should take care to recognize which pin is now different. probably EnableInterrupt.h handle this. well.

So. Learned atleast something about Functions, created some, and code is working properly at this point. Now im starting to write lineFollowingCode and start adding sensors to contraption.

#include <EnableInterrupt.h>

//Serial speed and channel amount
#define SERIAL_PORT_SPEED 9600
#define RC_NUM_CHANNELS 4

//Channel names
#define RC_CH1 0
#define RC_CH2 1
#define RC_CH3 2
#define RC_CH4 3

//Channels
#define RC_CH1_INPUT A0
#define RC_CH2_INPUT A1
#define RC_CH3_INPUT A2
#define RC_CH4_INPUT A3



//Interrupts
uint16_t rc_values[RC_NUM_CHANNELS];
uint32_t rc_start[RC_NUM_CHANNELS];
volatile uint16_t rc_shared[RC_NUM_CHANNELS];

void rc_read_values() {
  noInterrupts();
  memcpy(rc_values, (const void *)rc_shared, sizeof(rc_shared));
  interrupts();
}

void calc_input(uint8_t channel, uint8_t input_pin) {
  if (digitalRead(input_pin) == HIGH) {
    rc_start[channel] = micros();
  } else {
    uint16_t rc_compare = (uint16_t)(micros() - rc_start[channel]);
    rc_shared[channel] = rc_compare;
  }
}

void calc_ch1() {
  calc_input(RC_CH1, RC_CH1_INPUT);
}
void calc_ch2() {
  calc_input(RC_CH2, RC_CH2_INPUT);
}
void calc_ch3() {
  calc_input(RC_CH3, RC_CH3_INPUT);
}
void calc_ch4() {
  calc_input(RC_CH4, RC_CH4_INPUT);
}

void setup() {
  Serial.begin(SERIAL_PORT_SPEED);
  //pinMode(2, INPUT);
  //pinMode(3, INPUT);
  pinMode(RC_CH1_INPUT, INPUT);
  pinMode(RC_CH2_INPUT, INPUT);
  pinMode(RC_CH3_INPUT, INPUT);
  pinMode(RC_CH4_INPUT, INPUT);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(9, OUTPUT);

  //Relays OFF on start
  digitalWrite(13, LOW);
  digitalWrite(12, HIGH);
  digitalWrite(11, HIGH);
  digitalWrite(10, HIGH);
  digitalWrite(9, HIGH);



  enableInterrupt(RC_CH1_INPUT, calc_ch1, CHANGE);
  enableInterrupt(RC_CH2_INPUT, calc_ch2, CHANGE);
  enableInterrupt(RC_CH3_INPUT, calc_ch3, CHANGE);
  enableInterrupt(RC_CH4_INPUT, calc_ch4, CHANGE);
}

void loop() {
  //functions
 int func1();
 int func2();


  rc_read_values();
  Serial.print("CH1:");
  Serial.print(rc_values[RC_CH1]);
  Serial.print("\t");
  Serial.print("CH2:");
  Serial.print(rc_values[RC_CH2]);
  Serial.print("\t");
  Serial.print("CH3:");
  Serial.print(rc_values[RC_CH3]);
  Serial.print("\t");
  Serial.print("CH4:");
  Serial.println(rc_values[RC_CH4]);
  //delay(200);

  if (rc_values[RC_CH4]<1800){
    func1();
  }
  else
  {
    func2();
  }
 }
 
    //Relay controls
  void func2() {
  if (rc_values[RC_CH1] < 1600) {
    digitalWrite(9, HIGH);
  } else digitalWrite(9, LOW);

  if (rc_values[RC_CH1] > 1450) {
    digitalWrite(10, HIGH);
  } else digitalWrite(10, LOW);

  if (rc_values[RC_CH2] > 1450) {
    digitalWrite(11, HIGH);
  } else digitalWrite(11, LOW);

  if (rc_values[RC_CH2] < 1600) {
    digitalWrite(12, HIGH);
  } else digitalWrite(12, LOW);

  //AUXCHannel(n.1100-1900)
  if (rc_values[RC_CH3] > 1500) {
    digitalWrite(13, HIGH);
  } else digitalWrite(13, LOW);
  }

//FAILSAFE
  void func1() {
    digitalWrite(13, LOW);
    digitalWrite(12, HIGH);
    digitalWrite(11, HIGH);
    digitalWrite(10, HIGH);
    digitalWrite(9, HIGH);
  }

  

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.