radiocomando rc motor shield rev3

ciao, stavo cercando di pilotare un motore in dc a 12 volt tramite la motor shield rev3 e un radio comando rc della futaba con tx e rx.
sono riuscito a far muovere il motore solamente in avanti estrapolando parti di codice da un progetto trovato in rete, ma il problema è che lo skech che hotrovato è troppo elaborato,e riesco solo a fare girare il motore solo avanti e neanche bene, e dato che sono alle prime armi cercavo un esempio un pò piu semplice solo per muovere un motore con un telecomando a 2 canali(quello per le macchinine).da quel che ho capito bisogna decodificare i lalori ppm del telecomando per poi trasformali in pwm da mandare al motore ma per uno che non ne sa una mazza non è cosi semplice :).
quello che vorrei io è arrivare piano piano a contollare bene un motore dc avanti e indietro ch1 e un servo ch2 ,e poi integrare un giroscopio per supportare il servo.
ma piano piano ora mi accontento di fare muovere bene solo il motore dc.
grazie

Se il telecomando é uno di una macchinia da 2 soldi puó essere che non lavora in modo proporzionale ma solo on/off.
Ciao Uwe

no il telecomando è questo: http://www.astramodel.cz/manualy/futaba/futaba_2er_eng.pdf
il ricevitore è questo: http://manuals.hobbico.com/fut/2pcka-manual.pdf
non mi sembrano brutti no? io li usavo bene con la mia macchinina rc.

Devi leggere il segnale PPM che viene dal telecomando per esempio con pulseIn(). Poi definisci il valore corrispondente alla posizione centrale come motore fermo e a secondo del valore piú grande o piú piccolo di questo valore media la direzione e la.
Ciao Uwe

non è che mi butteresti giù un piccolo sckech di esempio perchè quei comandi non li ho mai usati.
non pretedo che tu venga qui a farmelo funzionare ,ma se con pazzienza riesci a starmi dietro un pò,tempo permettendo ,te ne sarei grato.

facendo girare un altro skech ho notato che spingendo la leva dell'acceleratore tutta in avanti mi da un valore di1100, e spingendola tutta indietro 1900,a riposo 1500.tutti e valori non sono stabili anno delle piccole variazioni ma penzo che sia normale.

lo skech è quest:
// This is the main code, it should run on the main processor.
// Read PPM signals from 2 (or 3) channels of an RC reciever and convert the values to PWM in either direction.
// digital pins 5 & 9 control motor1, digital pins 6 & 10 control motor2.
// DP 12 and 13 are neutral indicator lights.
// DP 2 and 3 are inputs from the R/C receiver.
// All analog pins are open.
//
// I also use a 2nd arduino to decode more channels for a Failsafe, as I use this code on large bots.
// JDW 2010
// www.rediculouslygoodlooking.com

int motor1_a = 5; // motor 1 outputs
int motor1_b = 9;

int motor2_a = 6; // motor 2 outputs
int motor2_b = 10;

int ledPin1 = 13; // led indicator lights
int ledPin2 = 12;
int ledPin3 = 14;

int servo1 = 2; // r/c channel 1
int servo2 = 3; // r/c channel 2
//int servo3 = 7;

int power = 4; // power for R/C receiver, stays HIGH (5v).

//int relay_Pin = 8;

unsigned int relay_val;

volatile unsigned long servo1_startPulse; //values for channel 1 signal capture
volatile unsigned servo1_val;
volatile int adj_val1;
volatile int servo1_Ready;

volatile unsigned long servo2_startPulse; //values for channel 2 signal capture
volatile unsigned servo2_val;
volatile int adj_val2;
volatile int servo2_Ready;

int deadband_high = 275;
int deadband_low = 235;

int pwm_ceiling = 256;
int pwm_floor = 255;

int low1 = 1100; // adjust these values if your R/C readings are above or below these for channels 1 and 2.
int high1 = 1900;
int low2 = 1100;
int high2 = 1900;

int n = 0;

void setup() {

//TCCR0B = TCCR0B & 0b11111000 | 0x03;
//TCCR1B = TCCR1B & 0b11111000 | 0x01;

Serial.begin(9600);

//motor1 pins
pinMode(motor1_a, OUTPUT);
pinMode(motor1_b, OUTPUT);

pinMode(motor2_a, OUTPUT);
pinMode(motor2_b, OUTPUT);

//pinMode(relay_Pin, OUTPUT);

pinMode(power, OUTPUT);

//led's
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
//pinMode(ledPin3, OUTPUT);

//PPM inputs from RC receiver
pinMode(servo1, INPUT); //Pin 2 as input
pinMode(servo2, INPUT); //Pin 3 as input
//pinMode(servo3, INPUT); //Pin 3 as input

digitalWrite(power, HIGH);
//digitalWrite(relay_Pin, LOW);

delay(1200);

attachInterrupt(0, rc1_begin, RISING); // catch interrupt 0 (digital pin 2) going HIGH and send to rc1()
attachInterrupt(1, rc2_begin, RISING); // catch interrupt 1 (digital pin 3) going HIGH and send to rc2()

}

////////// attach servo signal interrupts to catch signals as they go HIGH then again as they go LOW, then calculate the pulse length.

void rc1_begin() { // enter rc1_begin when interrupt pin goes HIGH.

servo1_startPulse = micros(); // record microseconds() value as servo1_startPulse

detachInterrupt(0); // after recording the value, detach the interrupt from rc1_begin

attachInterrupt(0, rc1_end, FALLING); // re-attach the interrupt as rc1_end, so we can record the value when it goes low

}

void rc1_end() {

servo1_val = micros() - servo1_startPulse; // when interrupt pin goes LOW, record the total pulse length by subtracting previous start value from current micros() vlaue.

detachInterrupt(0); // detach and get ready to go HIGH again

attachInterrupt(0, rc1_begin, RISING);

}

void rc2_begin() {

servo2_startPulse = micros();

detachInterrupt(1);

attachInterrupt(1, rc2_end, FALLING);

}

void rc2_end() {

servo2_val = micros() - servo2_startPulse;

detachInterrupt(1);

attachInterrupt(1, rc2_begin, RISING);

}
/////// servo interrupts end

/////// MAIN LOOP

void loop() {

///// channel 1 good signal check
if (servo1_val < 600 || servo1_val > 2400) { // only set the servo1_Ready flag if the value is a valid Servo pulse between 600-2400 microseconds.
servo1_Ready = false;
servo1_val = 1500;
}
else {
servo1_Ready = true; // if not, don't pass the value to be processed
}

///// channel 1 good signal check

if (servo2_val < 600 || servo2_val > 2400) {
servo2_Ready = false;
servo2_val = 1500;
}
else {
servo2_Ready = true;
}

////////// channel 1 motor update

if (servo1_Ready) {

servo1_Ready = false;
adj_val1 = map(constrain(servo1_val, 600, 2400), low1, high1, 0, 511);
constrain(adj_val1, 0, 511);

if (adj_val1 < 0) {
adj_val1 = 0;
}
if (adj_val1 > 511) {
adj_val1 = 511;
}

if (adj_val1 > deadband_high) {
//Forward
digitalWrite(motor1_b, LOW);
analogWrite(motor1_a, adj_val1 - pwm_ceiling);
digitalWrite(ledPin1, LOW);
}
else if (adj_val1 < deadband_low) {
//REVERSE
digitalWrite(motor1_a, LOW);
analogWrite(motor1_b, pwm_floor - adj_val1);
digitalWrite(ledPin1, LOW);
}
else {
//STOP
digitalWrite(motor1_a, LOW);
digitalWrite(motor1_b, LOW);
digitalWrite(ledPin1, HIGH); // turn on neutral light, turn motor pins off
}

}

///////////// channel 2 motor update

if (servo2_Ready) {

servo2_Ready = false;
adj_val2 = map(constrain(servo2_val, 600, 2400), low1, high1, 0, 511);
constrain(adj_val2, 0, 511);

if (adj_val2 < 0) {
adj_val2 = 0;
}
if (adj_val2 > 511) {
adj_val2 = 511;
}

if (adj_val2 > deadband_high) {
//Forward
digitalWrite(motor2_b, LOW);
analogWrite(motor2_a, adj_val2 - pwm_ceiling);
digitalWrite(ledPin2, LOW);
}
else if (adj_val2 < deadband_low) {
//REVERSE
digitalWrite(motor2_a, LOW);
analogWrite(motor2_b, pwm_floor - adj_val2);
digitalWrite(ledPin2, LOW);
}
else {
//STOP
digitalWrite(motor2_a, LOW);
digitalWrite(motor2_b, LOW);
digitalWrite(ledPin2, HIGH); // turn on neutral light, turn motor pins off
}

}

//print values to Serial monitor in Arduino IDE
Serial.print("ch1: ");
Serial.print(adj_val1);
Serial.print(" ");
Serial.print("rc1: ");
Serial.print(servo1_val);
Serial.print(" ");
Serial.print("ch2: ");
Serial.print(adj_val2);
Serial.print(" ");
Serial.print("rc2: ");
Serial.print(servo2_val);
Serial.print(" ");
Serial.print("loop counter: ");
Serial.print(n);
Serial.println(" ");

//n++;

}

allora, ho provato ad apportare qualche modifica al codice che ho postato ieri, eliminando le parti che riguardavano il secondo canale,motore e la parte dei led che non mi interessano per ora.
il problema è che funziona solo a metà cioè quando aziono il radiocomando in retro il motore risponde bene variando la velocità a piacimento,quando è a riposo manettino del radiocomando il motore è fermo, ma quando porto il manettino in avanti per accelerare il motore non si muove non da segni di vita.
sicuramente c'è un errore ne codice,errore che non trovo essendo come ripeto alle prime armi.di fatti non sono riuscito a capire tutto il funzionamento del codice ma solo una parte.se qualcuno potesse dare un occhiata al codice e dirmi dove sbaglio gliene sarei grato.
Eccco il codice:
// This is the main code, it should run on the main processor.
// Read PPM signals from 2 (or 3) channels of an RC reciever and convert the values to PWM in either direction.
// digital pins 5 & 9 control motor1, digital pins 6 & 10 control motor2.
// DP 12 and 13 are neutral indicator lights.
// DP 2 and 3 are inputs from the R/C receiver.
// All analog pins are open.
//
// I also use a 2nd arduino to decode more channels for a Failsafe, as I use this code on large bots.
// JDW 2010
// www.rediculouslygoodlooking.com

int motor1_a = 3; // motor 1 outputs
int motor1_b = 12;

int servo1 = 2; // r/c channel 1

int power = 4; // power for R/C receiver, stays HIGH (5v).

//int relay_Pin = 8;

unsigned int relay_val;

volatile unsigned long servo1_startPulse; //values for channel 1 signal capture
volatile unsigned servo1_val;
volatile int adj_val1;
volatile int servo1_Ready;

int deadband_high = 275;
int deadband_low = 235;

int pwm_ceiling = 256;
int pwm_floor = 255;

int low1 = 1100; // adjust these values if your R/C readings are above or below these for channels 1 and 2.
int high1 = 1900;

int n = 0;

void setup() {

//TCCR0B = TCCR0B & 0b11111000 | 0x03;
//TCCR1B = TCCR1B & 0b11111000 | 0x01;

Serial.begin(9600);

//motor1 pins
pinMode(motor1_a, OUTPUT);
pinMode(motor1_b, OUTPUT);

//pinMode(relay_Pin, OUTPUT);

pinMode(power, OUTPUT);

//PPM inputs from RC receiver
pinMode(servo1, INPUT); //Pin 2 as input

digitalWrite(power, HIGH);
//digitalWrite(relay_Pin, LOW);

delay(1200);

attachInterrupt(0, rc1_begin, RISING); // catch interrupt 0 (digital pin 2) going HIGH and send to rc1()

}

////////// attach servo signal interrupts to catch signals as they go HIGH then again as they go LOW, then calculate the pulse length.

void rc1_begin() { // enter rc1_begin when interrupt pin goes HIGH.

servo1_startPulse = micros(); // record microseconds() value as servo1_startPulse

detachInterrupt(0); // after recording the value, detach the interrupt from rc1_begin

attachInterrupt(0, rc1_end, FALLING); // re-attach the interrupt as rc1_end, so we can record the value when it goes low

}

void rc1_end() {

servo1_val = micros() - servo1_startPulse; // when interrupt pin goes LOW, record the total pulse length by subtracting previous start value from current micros() vlaue.

detachInterrupt(0); // detach and get ready to go HIGH again

attachInterrupt(0, rc1_begin, RISING);

}

/////// servo interrupts end

/////// MAIN LOOP

void loop() {

///// channel 1 good signal check
if (servo1_val < 600 || servo1_val > 2400) { // only set the servo1_Ready flag if the value is a valid Servo pulse between 600-2400 microseconds.
servo1_Ready = false;
servo1_val = 1500;
}
else {
servo1_Ready = true; // if not, don't pass the value to be processed
}

///// channel 1 good signal check

///// channel 1 motor update

if (servo1_Ready) {

servo1_Ready = false;
adj_val1 = map(constrain(servo1_val, 600, 2400), low1, high1, 0, 511);
constrain(adj_val1, 0, 511);

if (adj_val1 < 0) {
adj_val1 = 0;
}
if (adj_val1 > 511) {
adj_val1 = 511;
}

if (adj_val1 > deadband_high) {
//Forward
digitalWrite(motor1_b, LOW);
analogWrite(motor1_a, adj_val1 - pwm_ceiling);
}
else if (adj_val1 < deadband_low) {
//REVERSE
digitalWrite(motor1_a, LOW);
analogWrite(motor1_b, pwm_floor - adj_val1);
}
else {
//STOP
digitalWrite(motor1_a, LOW);
digitalWrite(motor1_b, LOW);

}

}

//print values to Serial monitor in Arduino IDE
Serial.print("ch1: ");
Serial.print(adj_val1);
Serial.print(" ");
Serial.print("rc1: ");
Serial.print(servo1_val);
Serial.print(" ");
Serial.print("loop counter: ");
Serial.print(n);
Serial.println(" ");

//n++;

}
Grazie

Hi,

Sorry, no Italian but your code has a problem, no protection of shared variable access.

Duane B
rcarduino.blogspot.com

thanks, now I study the links I've posted and let you know some

direi che l'errore è quì:

//forward
analogWrite(motor1_a, adj_val1 - pwm_ceiling); 

//backward
analogWrite(motor1_b, pwm_floor - adj_val1);

non vedo perchè, a parte motor1_a e motor1_b il secondo parametro debba variare. Prova a cambiare da

//forward
analogWrite(motor1_a, adj_val1 - pwm_ceiling);

a

//forward
analogWrite(motor1_b, adj_val1 - pwm_ceiling);

in oltre non stai "proteggendo" correttamente le variabili che sono sia usate dell'interrupt che dal loop, come DuaneB suggerisce.
usa pulseIn, e poi passa agli interrupt

Grazie lesto per la risposta,ora non ho tempo ma sta sera appena riesco e provo a fare la modifica che mi hai detto.
cosa intendi per prova ad usare i pulsein e poi gli interrupt?

stai usando in modo errato gli interrupt. usa pulseIn e rimuovili, poi quando funziona tutto li rimettiamo corretti

insomma devo cancellare tuta la parte che attaca e stacca gli interrupt e al posto di quella devo unsare il pulsein?se è cosi vado a vedere come si usa il pulsein..

devo dirgli che se arriva un segnale dal low1 1100 il pulsein vain low(motore gira in retro) e segli aarriva un segnale dal high1 1900 il pulse in va in high/motore gira avanti.giusto?

1500 +-100(circa)microsec è il segnale PPM che indica il centro dello stick. quindi non solo puoi comandare avanti e indietro, ma pure la velocità

niente non solo ho provato e riprovato decine di codici diversi exnovi o modifiche di altri,ma tutto quello che sono riuscito a fare è far girare il motore ininterrottamente senza nessun controllo.
mi fuma la testa...
devo essere sincero,senza una minima base di conoscenza informatica di programmazzione,è quasi impossibile solo capire quello che si sta scrivendo, figuriamoci capire i codici più complessi.per chi volesse farsi due risate :):
// This is the main code, it should run on the main processor
// digital pins 3 & 12 control motor1,
// DP is inputs from the R/C receiver.
// All analog pins are open.
//

int pwmmotor = 3; // motor 1 PWM
int dirmotor = 12; // motor 1 DIR
int servo1 = 2; // r/c channel 1
int power = 4; // power for R/C receiver, stays HIGH (5v).
int durata = 0;

volatile unsigned long servo1_startPulse;
volatile unsigned servo1_val;
volatile int adj_val1;
volatile int servo1_Ready;

int low1 = 1100; // adjust these values if your R/C readings are above or below these for channels 1
int high1 = 1900;
int n = 0;

void setup() {

Serial.begin(9600);

//motor1 pins
pinMode(pwmmotor, OUTPUT);
pinMode(dirmotor, OUTPUT);

//pinMode(relay_Pin, OUTPUT);

pinMode(power, OUTPUT);

//PPM inputs from RC receiver
pinMode(servo1, INPUT); //Pin 2 as input

digitalWrite(power, HIGH);
//digitalWrite(relay_Pin, LOW);

delay(1200);

}
/////// MAIN LOOP

void loop() {

///// channel 1 good signal check
if (servo1_val < 1100 || servo1_val > 1900) { // only set the servo1_Ready flag if the value is a valid Servo pulse between 1100-1900 microseconds.
servo1_Ready = false;
servo1_val = 1500;
durata = pulseIn(servo1,HIGH); // durata impulso
}

else {
servo1_Ready = true; // if not, don't pass the value to be processed
}

if (servo1_Ready) {

servo1_Ready = false;
adj_val1 = map(constrain(servo1_val, 1100, 1900), low1, high1, 0, 511);
constrain(adj_val1, 0, 551);

if (adj_val1 < 0) {
adj_val1 = 0;
}
if (adj_val1 > 551) {
adj_val1 = 551;
}
if(durata < 1650) {
digitalWrite (dirmotor,LOW);
analogWrite (pwmmotor,adj_val1);
}
if(durata > 1450) {
digitalWrite (dirmotor,HIGH);
analogWrite (pwmmotor,adj_val1);
}
}

//print values to Serial monitor in Arduino IDE
Serial.print("ch1: ");
Serial.print(adj_val1);
Serial.print(" ");
Serial.print("rc1: ");
Serial.print(servo1_val);
Serial.print(" ");
Serial.print("loop counter: ");
Serial.print(n);
Serial.println(" ");

//n++;

}

allora, usa il tag [ code][ /code] se no non si capisce una mazza.
puoi allegare anche l'output dell'arduino su seriale?

edit: anche schemi di collegamento con i componenti utilizzati

io sò che ci sono moltissimi errori nel mio pseudo codice e capisco quanda pazienza stai portando con me e ti ringrazio,

allora :
1:Motor shield rev3 agganciata ad arduino
2:motore 12v collegato alla motor shield rev3 sul uscita "A" dove PWM= pin 3 arduino e DIR=pin 12 arduino
3:alimentazione ricevente RC su 5v e GND arduino
4:rirno del segnale della ricevente = pin 2 arduino
5:alimentazione Arduino esterna tramite alimentatore 12v 1A


int pwmmotor = 3; * // motor 1 PWM*
int dirmotor = 12; // motor 1 DIR
int servo1 = 2; // r/c channel 1
int power = 4; // power for R/C receiver, stays HIGH (5v).
int durata = 0;

volatile unsigned long servo1_startPulse;
volatile unsigned servo1_val;
volatile int adj_val1;
volatile int servo1_Ready;

int low1 = 1100;
int high1 = 1900;
int n = 0;

void setup() {

Serial.begin(9600);

pinMode(pwmmotor, OUTPUT);
pinMode(dirmotor, OUTPUT);
pinMode(power, OUTPUT);
pinMode(servo1, INPUT);

digitalWrite(power, HIGH);

delay(1200);
}

void loop() {

if (servo1_val < 1100 || servo1_val > 1900) {
servo1_Ready = false;
servo1_val = 1500;
durata = pulseIn(servo1,HIGH); // durata impulso
}

else {
servo1_Ready = true;
}

if (servo1_Ready) {

servo1_Ready = false;
adj_val1 = map(constrain(servo1_val, 1100, 1900), low1, high1, 0, 511);
constrain(adj_val1, 0, 551);

if (adj_val1 < 0) {
adj_val1 = 0;
}
if (adj_val1 > 551) {
adj_val1 = 551;
}
if(durata < 1650) {
digitalWrite (dirmotor,LOW);
analogWrite (pwmmotor,adj_val1);
}
if(durata > 1450) {
digitalWrite (dirmotor,HIGH);
analogWrite (pwmmotor,adj_val1);
}
}

Serial.print("ch1: ");
Serial.print(adj_val1);
Serial.print(" ");
Serial.print("rc1: ");
Serial.print(servo1_val);
Serial.print(" ");
Serial.print("loop counter: ");
Serial.print(n);
Serial.println(" ");

}


Serial monitor:

ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0
ch1: 255 rc1: 1500 loop counter: 0

quando ho provato un altro codice ho visto che il valore rc1 variava da 1100 a 1900 ma in questo codice no.
Fammi saperese ti ho detto tutto e chiaro o hai bisogno di altro.

USA IL TAG CODE!

allora la

durata = pulseIn(servo1,HIGH);          // durata impulso

la fai ogni loop, non capisco che diavolo serva la if che hai messo, se non per far casino.

adj_val1 va da 0 a 255, non capisco cosa centri il 551

insomma sistema il codice, in pratica nel loop deve rimanere:
1 pulseIn (ovvero prendere l'input)
2 la gestione del motore

if(durata < 1650) { 
         digitalWrite (dirmotor,LOW);
         analogWrite (pwmmotor,adj_val1);
    }
         if(durata > 1450) { 
         digitalWrite (dirmotor,HIGH);
         analogWrite (pwmmotor,adj_val1);
    }

aggiustando però il fatto che le due durate "cozzano" tra di loro
3 il codice di debug sulla Serial.

devi assicurati che il valore di rc1 vari da 1100 a 1900, e che il motore risponda di conseguenza.