problema con encoder ed altro....

Saluti a tutti... ... in questi giorni di vacanze ho lavorato su un progetto he avevo nel cassetto da un poco ...

il progetto prevede il controllo due servi analogici tramite due encoder, un LCD per visualizzare istantaneamente alcuni parametri di funzionamento, etc..

Come LCD uso uno con con driver HITACHI, come encoder so due encoder a quadratura di fase, ottici, ricavati da un vecchio mouse.. così per fare le prove...

tutto funziona bene finchè non attivo gli interrupt: i servi funzionano bene, si impostonano secondo i dati meorizzati sulla eeprom e secondo le modalità di funzionamennto impostate... tutto ok. Visualizzo tutto sull'lcd, esattamente come io avevo in mente...

anche gli encoder funzionano bene, finchè li uso separatamente, dai servo, ma nello stesso progetto con i servo niente..

al primo avvio del primo servo l'LCD va in panne..... stacco gli encoder, resetto e funziona di nuovo tutto, anche senza modificare lo script ...

oppure stacco i servo e di nuovo tutto il resto funziona anche senza modificare lo script...

mi sono fatto l'idea che l'azionamento dei servo (analogici) introduce delle perturbazioni che fanno saltare gli interrupt che a loro volta fa saltare il funzionamento dell'LCD ... ma non so che pesci pigliare.... ho anche provato ada limentare separatamente i servo.. ma niente.... non funge e basta. al primo attach dei servo salta tutto.. il display impazzisce e non fa vedere più niente, anche se continuoa vedere che il micro fuzniona perchè azionando gli altri comandi vedo che i servo ubbidiscono....

giusto per dare un'dea dello script che è un po complesso posto qui una delle funzioni principali:

void eseguiModo1()   // Modo memory (SOLO LETTURA)
{
aggiornaLCD (1, 1);
leggiInputP2e3();

 if (band != P2 || ant != P3)  // prima fase: individua se ci sono stati cambiamenti
 {
  angC1 = (EEPROM.read(11 + 20 * (P2-1) + (P3-1) * 5 + 0));
  angC2 = (EEPROM.read(11 + 20 * (P2-1) + (P3-1) * 5 + 1));
  L     = (EEPROM.read(11 + 20 * (P2-1) + (P3-1) * 5 + 2));
//SWR   = (EEPROM.read(11 + 20 * (P2-1) + (P3-1) * 5 + 3));

  aggiornaLCD (2, P2);  aggiornaLCD (3, P3);  aggiornaLCD (4, angC1);  aggiornaLCD (5, angC2);  aggiornaLCD (6, L);
  //Serial.print ("\n Banda:");  Serial.print (P2);  Serial.print ("  Ant:");  Serial.print (P3);
  band = P2; ant = P3;
  boolTune1 = false; countTune1 = millis();
  tone(A5, 4000);   // turn the LED on (HIGH is the voltage level)
  
 }

 if ((millis() - countTune1 > 30 ) ) {noTone(A5);}  // spegne il tono che segnala il cambio

 if ((millis() - countTune1 > ritTune) && !boolTune1) // seconda fase attiva i servo se non ci sono modifiche per ritTune mS....
    {
     myservoC1.attach(C1); myservoC2.attach(C2);
     myservoC1.write(angC1); myservoC2.write(angC2);
     // imposta L
     boolTune1 = true; boolTune2 = false; countTune2 = millis();
    }

if  ((millis() - countTune2 > (1300*1.1)) && !boolTune2)  // terza fase ... spegne i servo dopo 1300 * 1,1 mS
    {
     myservoC1.detach();
     myservoC2.detach();
     boolTune2 = true;
    }

}

qui la funzine aggiorna LCD

aggiornaLCD (int i, int valore)
{
  switch (i)
   {
    case 1:
      lcd.setCursor(0, 0) ; lcd.print("Md "); lcd.print(valore); lcd.print(" "); break;
    case 2:
      lcd.setCursor(5, 0) ; lcd.print("Bd "); lcd.print(valore); lcd.print(" "); break;
    case 3:
      lcd.setCursor(11, 0); lcd.print("An "); lcd.print(valore); lcd.print(" "); break;
    case 4:
      lcd.setCursor(0, 1) ; lcd.print("C"); lcd.print(valore); lcd.print(" "); break;
    case 5:
      lcd.setCursor(5, 1) ; lcd.print("C"); lcd.print(valore); lcd.print(" "); break;
    case 6:
      lcd.setCursor(10, 1); lcd.print("L"); lcd.print(valore); lcd.print(" "); break;
    case 7:
      lcd.setCursor(13, 1); lcd.print("+"); lcd.print(valore); lcd.print(" "); break;
     case 8:
      lcd.setCursor(13, 1); lcd.print("-"); lcd.print(valore); lcd.print(" "); break;
 }

è qui il controllo degli encoder, che in altri scketch funziona bene.....

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);

  pinMode(4, INPUT);
  pinMode(5, INPUT);

  attachInterrupt(0, updateEncoder0, RISING);
  attachInterrupt(1, updateEncoder1, RISING);
 }

void updateEncoder0()
{
  if ((PIND & B00010000)>>4)
      {angC1++;} else {angC1--;}
}

void updateEncoder1()
{
  if ((PIND & B00100000)>>5)
       {angC2++;} else {angC2--;}
}

ripeto... il codice credo che vada bene.... credo che sia un problema di filtraggio di qualche disturbo che i servo inviano agli interrupt e che a loro volta mettono in crisi l'LCD...

cosa mi suggerite? ..... qualche idea?..... grazie Saluti a tutti Paolo

niente??? ... neanche una mezza idea???

Troppo stress, troppa fatica leggere tutto il codice. Poi siamo sotto le feste, la panza piena, i riflessi lenti, il corpo e la mente che si trascinano stanchi... XD

Ciao Babbuino.... grazie comunque per la risposta ...

si hai ragione.... infatti stavo per non metterne niente di codice.... perchè il problema credo sia solo hardware... che ho cercato di sintetizzare così: - quando si attiva il servo (attach).. parte l'LCD.. ma questo sucecde solo quando uso gli interrupt per gestire l'encoder rotativo, ottico..

se non abilito gli interrupt oppure se stacco fisicamente l'encoder (disconnetto fisicamente il canale A e B di ciascuno dei due encoder) .. tutto funziona regolarmente... e funziona bene pure se uso l'encoder in un altro scketc semplice, solo visualizzando le variabili incrementate/decrementate sull'LCD. Sulla oprta seriale crea sempre dei problemi. Mi pare di aver capito che l'interrupt 0 è in qualche modo crea problemi sulla seriale.

L'encoder lo gestisco tramite un interrup controllondo solo un fronte dell'impulso (di salita o di discesa) e poi controllando il bit presente sul pin dove è collegato l'altro canale. Siccome è un encoder ottino con ci sono rimbalzi, e non mi serve discriminare le altre posizioni, mi basta un impulso per ogni ciclo.

la domanda è questa: 1) è verosimile che l'attivazoine dei servo faccia giungere dei segnali e/o rumore che attivi ogni volta gli interrupt ? 2) se si.... come posso cercare di filtrare?

visto senza codice ... facile facile.. e comunque andiamoci piano con il panettone e lo spumante.... ciao

Se stai alimentando i servo con il 5V di Arduino quello che ti succede è più che normale, devi alimentarli in modo separato da Arduino.

... no astro.... il problema si verfica anche se alimento i servo separatamente (provato) .... invece, non si verifica se alimento tutto dall'arduino ma con gli encoder fisicamente discomessi ....

Te la lancio lì, così a caso, mentre sto mangiando un metro quadrato di focaccia: quando esci dalla routine di Interrupt, prova a disabilitarli con l'istruzione cli(); (magari lo hai già fatto), per poi settarli un pò più in là con l'istruzione sei(); almeno capisci se è l'interrupt il problema.

.. astro.... ok.. domani faccio un po di prove.. prima non posso...

... ps.. ti faccio i complimenti perchè ti funzionano i neuroni anche in contemporane a alle mandibole. Io non ci riesco, quando le mandibole cominciano a lavorare assorbono quasi tutte le risorse , mandano in tilt tutto il resto. dev'essere una qualche perturbazione bio-elettrica che non fà funzionare niente di quasi tutto il resto....

saluti