@uwefed:
Perché misuri la velocitá del motore? …
Cioè dici perchè non provare senza retroazione?
Si penso proprio che volevi dire questo e infatti l’ho fatto.
#include "pins_arduino.h"
#define encoder0PinA 4 //PIND 0b00010000
#define encoder0PinB 5 //PIND 0b00100000
volatile long encoder0Pos = 0;
volatile unsigned int stateEncoder0PinA;
volatile unsigned int stateEncoder0PinB;
ISR(PCINT2_vect)
{
//PCint(0);
// Pin Arduino 4 (PD4 PIN6 PCINT20), 5 (PD5 PIN11 PCINT21)
// se lo stato di encoder0PinA è cambiato, registra lo stato corrente
// e chiama encoder0ChA()
if ((PIND & 0b00010000) != stateEncoder0PinA)
//if (digitalRead(encoder0PinA) != stateEncoder0PinA)
{
// misura il periodo della frequenza generata dall'encoder
stateEncoder0PinA = (PIND & 0b00010000);
//stateEncoder0PinA = digitalRead(encoder0PinA);
encoder0ChA();
}
// se lo stato di encoder0PinB è cambiato, registra lo stato corrente
// e chiama encoder0ChB()
if ((PIND & 0b00100000) != stateEncoder0PinB)
//if (digitalRead(encoder0PinB) != stateEncoder0PinB)
{
stateEncoder0PinB = (PIND & 0b00100000);
//stateEncoder0PinB = digitalRead(encoder0PinB);
encoder0ChB();
}
}
void encoder0ChA()
{
if (stateEncoder0PinA) {
// check channel B to see which way encoder is turning
if (PIND & 0b00100000)
//if (digitalRead(encoder0PinB) == HIGH)
{
encoder0Pos--; // CCW
}
else
{
encoder0Pos++; // CW
}
}
else
{
// check channel B to see which way encoder is turning
if (PIND & 0b00100000)
//if (digitalRead(encoder0PinB) == HIGH)
{
encoder0Pos++; // CW
}
else
{
encoder0Pos--; // CCW
}
}
}
void encoder0ChB()
{
// check state changed on channel B
if (stateEncoder0PinB)
{
// check channel A to see which way encoder is turning
if (PIND & 0b00010000)
//if (digitalRead(encoder0PinA) == HIGH)
{
encoder0Pos++; // CW
}
else
{
encoder0Pos--; // CCW
}
}
else
{
// check channel A to see which way encoder is turning
if (PIND & 0b00010000)
//if (digitalRead(encoder0PinA) == HIGH)
{
encoder0Pos--; // CCW
}
else
{
encoder0Pos++; // CW
}
}
}
#define ledPin 13
#define pwmPin 9
void setup()
{
// prescaler 8 credo?
TCCR1B |= (1<<CS11);
Serial.begin(115200);
Serial.flush();
pinMode(ledPin, OUTPUT);
pinMode(encoder0PinA, INPUT);
pinMode(encoder0PinB, INPUT);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(pwmPin, OUTPUT);
stateEncoder0PinA = (PIND & 0b00010000);
//stateEncoder0PinA = digitalRead(encoder0PinA);
stateEncoder0PinB = (PIND & 0b00100000);
// PIN CHANGED ENABLED
PCICR |= (1 << PCIE2); // Abilita l'iterrupt su PORTD
PCMSK2 |= (1 << PCINT20); // Abbilita il vettore PCINT20 PD4 ARDUINO(4)
PCMSK2 |= (1 << PCINT21); // Abbilita il vettore PCINT21 PD5 ARDUINO(5)
}
int position;
int byteCommand;
#define onWards 1
#define backWards -1
#define motorOff 0
#define motorOn 1
int startSlow;
int goMotor;
int motorPower = 0;
int dutyc;
void command(int comm)
{
if (comm == 'A')
{
position = 0;
startSlow = 200;
goMotor = backWards;
motorPower = motorOn;
dutyc = 400;
}
if (comm == 'S')
{
position = 5760;
startSlow = position - 200;
goMotor = onWards;
motorPower = motorOn;
dutyc = 400;
}
}
void serialTx()
{
//Serial.println(error);
//Serial.println(widthEncoder0PinA);
//Serial.println(dutycpluserror);
}
void loop() {
if ((encoder0Pos == 0) || (encoder0Pos == 5760))
{
digitalWrite(ledPin, HIGH);
}
else
{
digitalWrite(ledPin, LOW);
}
if (encoder0Pos == position)
{
digitalWrite(3, LOW);
digitalWrite(2, LOW);
analogWrite(pwmPin, 1023);
delay(20);
analogWrite(pwmPin, 0);
motorPower = motorOff;
}
if (motorPower == motorOn)
{
if (goMotor == onWards)
{
digitalWrite(3, HIGH);
digitalWrite(2, LOW);
analogWrite(pwmPin, dutyc);
}
if (goMotor == backWards)
{
digitalWrite(2, HIGH);
digitalWrite(3, LOW);
analogWrite(pwmPin, dutyc);
}
}
if (Serial.available() > 0)
{
byteCommand = Serial.read();
command(byteCommand);
}
// if ((encoder0Pos < 5760) && (encoder0Pos > 0))
// {
// serialTx();
// }
}
Difetti di questa soluzione:
Si ferma sempre dopo la posizione in cui azzero il duty cycle, Newton aveva ragione. 
Il movimento non è fluido e la velocità non è costante, perchè c’è un’attrito volvente che non è costante (cinghia, boccole ecc)
@lesto:
Che bello un nick facile da ricordare.
occhio alla seriale! ha una velocità di invio che è fissata all’inizio, ed essendo una chiamata bloccante e lenta, può sballarti i valori letti (soprattutto la sottrazione tra millis), a meno che l’input e il calcolo non lo fai con interrupt, però a questo punto possono nascere problemi di parallelismo (esempio interrupt che cambia il dato mentre la serial ne ha già scritto parte…)
Quindi, come si può ovviare, ne avevo il sospetto ora come lo hai esposto tu mi ha dato la certezza, cioè non mi posso fidare, ho letto che le routin ISR interrompono in qualunque momento, con la possibilità molto frequente di rovinare i calcoli effettuati nel loop, in pratica sulle operazioni che non sono atomiche conviene spegnere l’interrupt “fai operazioni non atomiche” riaccendi interrupt.
@gbm:
Si si, pico l’ho già visto, ho seguito senza fiatare, è incredibile che con così poco codice riesca a stare in equilibrio.
Nel tuo caso, se hai un encoder rotativo / di movimento preciso, basta quello credo, anche se è di certo interessante sperimentare il PID con piu’ input.
Solo che un encoder da informazioni solo quando è in movimento, un potenziometro anche quando sta fermo.
[edit]Spero possa esserti utile per la tua sperimentazione.[/edit]
Si mi sarà di sicuro utile, ultimamente non ho più seguito lo sviluppo di pico, il problema che io sono uno a leggere e voi siete in centomila, ma se pò fà sta vita. 
Ok grazie per gli interventi che spero possano essere utili anche ad altri.
Ciao.