Salve a tutti!
Possiedo una ARDUINO Uno r3 e una ARDUINO Mega 2560, ma i vincoli di progetto mi impongono di usare la prima piattaforma. L'idea finale del progetto è ancora da definirsi:
1 volevo arrivare a leggere senza problemi i dati provenienti da una imu (mpu6050 acc+gyro)
2 volevo comandare due motori lego nxt con encoder (vedi link)
https://www.google.it/search?q=motore+lego+nxt&client=firefox-a&hs=StL&rls=org.mozilla:it:official&channel=sb&source=lnms&tbm=isch&sa=X&ei=09poU9raIpSGyQOziYG4DA&ved=0CAkQ_AUoAg&biw=1280&bih=688
L'idea iniziale era fare un mini segway o balancing robot, ma non sono + certo di cosa diventerà e non mi pongo il problema ora che di problemi ne devo ancora risolvere tanti!
DEVO QUINDI USARE ARDUINO UNO REV3
LA MEGA RISOLVEREBBE TUTTO :0 :0 :0 :0 :0
Il punto 1 è stato risolto, non senza difficoltà: la IMU per funzionare sfrutta un interrupt, esattamente l'int 0 pin 2. Posto soltanto un pezzetto di codice per chiarezza; proviene dall'ormai famoso codice di jeff rowberg riadattato per SPI.
// enable Arduino interrupt detection, this will execute dmpDataReady whenever there is an interrupt,
// independing on what this sketch is doing at that moment
// http://arduino.cc/en/Reference/AttachInterrupt
Serial.print("Enabling interrupt detection... ");
// attachInterrupt(interrupt, function, mode) specifies a function to call when an external interrupt occurs
// ArduIMU+ V3 has ATMEGA328 INT0 / D2 pin 32 (input) connected to MPU-6000 INT pin 12 (output)
[b]attachInterrupt(0, dmpDataReady, RISING); // the 0 points correctly to INT0 / D2[/b]
// -> if there is an interrupt from MPU-6000 to ATMEGA328, boolean mpuInterrupt will be made true
byte mpuIntStatus = SPIread(0x3A, ChipSelPin1); // by reading INT_STATUS register, all interrupts are cleared
VENIAMO AL PROBLEMA VERO E PROPRIO...
Ora si tratta di comandare UN motore nxt con encoder: ognuno di questi encoder ha 5 fili, due dei quali servono x leggere l'encoder, ma non credo si possa usare uno solo di questi due fili CAUSA perdita di risoluzione o proprio mancato funzionamento. Giusto?
Secondo le specifiche Arduino uno possiede 2 pin di interrupt:
External Interrupts: 2 and 3. These pins can be configured to trigger an interrupt on a low value, a rising or falling edge, or a change in value. See the attachInterrupt() function for details.
quindi se voglio usare sulla mia piattaforma la imu e l'encoder insieme sono obbligato ad usare un interrupt x l'una e uno x l'altra:
MA IO NE VORREI USARE DUE X L'ENCODER PER OTTENERE MIGLIORI RISULTATI.
COSA FARESTE?
IO SONO PER IL LASCIARE STARE LA IMU E CERCARE DI RISOLVERE IL PROBLEMA LEGGENDO UN ENCODER BENE CON DUE FILI, ma significa, essendo solo due gli interrupt esterni, creare una routine di interrupt per pin diversi da pin2 e pin3, o almeno, questo è quello che ho capito nelle miei ''crociere'' online.
Questo è il classico modo per leggere gli interrupt e funziona bene, ma usa il pin due che a me serve! =(
#define encoderPinA 2
#define encoderPinB 3
volatile int encoderCount = 0;
volatile float angle = 0;
volatile float angle_previous = 0;
volatile float angle_post = 0;
void doEncoderA(){ // interrupt 0 function
if (digitalRead(encoderPinA) == HIGH) { // look for a low-to-high on channel A
if (digitalRead(encoderPinB) == LOW) { // check channel B to see which way encoder is turning
encoderCount = encoderCount + 1;
}
else {
encoderCount = encoderCount - 1;
}
}
else { // must be a high-to-low edge on channel A
if (digitalRead(encoderPinB) == HIGH) { // check channel B to see which way encoder is turning
encoderCount = encoderCount + 1;
}
else {
encoderCount = encoderCount - 1;
}
}
angle = 0.00105*encoderCount; // unit: radian
// angle= angle*(180/?);
// angle= angle* 57.295;
}
void doEncoderB(){ // interrupt 1 function
if (digitalRead(encoderPinB) == HIGH) { // look for a low-to-high on channel B
if (digitalRead(encoderPinA) == HIGH) { // check channel A to see which way encoder is turning
encoderCount = encoderCount + 1;
}
else {
encoderCount = encoderCount - 1;
}
}
else { // must be a high-to-low edge on on channel B
if (digitalRead(encoderPinA) == LOW) { // check channel B to see which way encoder is turning
encoderCount = encoderCount + 1;
}
else {
encoderCount = encoderCount - 1;
}
}
angle = 0.00105*encoderCount; // unit: radian
// angle= angle*(180/?);
// angle= angle* 57.295;
}
void setup() {
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
attachInterrupt(0, doEncoderA, CHANGE);
attachInterrupt(1, doEncoderB, CHANGE);
Serial.begin (9600); // for debugging
}
void loop() {
Serial.print("counter: ");
Serial.print(encoderCount, DEC);
Serial.print(" - ");
Serial.print("angle: ");
Serial.print(angle, 4);
Serial.println(";");
delay(500);
}
Grazie al cielo sul forum di arduino ho trovato qualcuno che utilizza con successo interrupt su pin diversi da pin 2 e 3:
http://forum.arduino.cc/index.php?topic=80928.0
Qualche consiglio x capire il codice?
Mi basta una linea guida per capire come scrivere un programma che legga gli encoder!