Bonsoir
Alors voila, j'ai besoin d'utiliser un codeur comme interface pour un projet en cours. J'essaye donc plusieurs trucs, et finalement un bout de code à base de PCINT me semble le plus approprié dans mon cas. Ce code est une adaptation d'un code tiré du livre de Clemens Valens"maitrisez les microcontroleurs à l'aide d'arduino".
Voici donc ce code :
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
int pin_sw = 10;
int pin_a = 11;
int pin_b = 12;
int pin_out = 6;
int state = 0;
int state_sub = 0;
volatile int counter = 0;
volatile boolean flag = false;
volatile boolean flagbtn = false;
int valeur = 0;
LiquidCrystal_I2C lcd(0x20,20,4);
void encoder_read(void)
{
uint8_t pin_states = PINB & PCMSK0;
// Push button press.
if ((pin_states&0x04)==0)
{
flagbtn += 1;
}
pin_states = (pin_states>>3)&0x03;
// state is now 0, 1, 2 or 3.
if (pin_states!=state)
{
// Exor the old & new states to determine the rotation direction.
int inc = ((pin_states>>1)^state)&0x01;
if (inc==0) inc = -1;
state = pin_states;
// Reset on change of direction.
if ((inc<0 && state_sub>0) || (inc>0 && state_sub<0)) state_sub = 0;
state_sub += inc;
if (state_sub<=-4 || state_sub>=4)
{
state_sub -= (inc<<2);
counter += inc;
flag = true;
}
}
}
ISR(TIMER2_COMPA_vect)
{
bitClear(TIMSK2,OCIE2A); // Disable timer2 interrupts.
encoder_read();
bitSet(PCIFR,PCIF0); // Clear pending interrupts.
bitSet(PCICR,PCIE0); // Enable PCINT0-7.
}
ISR(PCINT0_vect)
{
bitClear(PCICR,PCIE0); // Disable PCINT0-7.
bitSet(TCCR2A,WGM21); // CTC mode.
bitSet(TCCR2B,CS20);
bitSet(TCCR2B,CS22); // Clk div by 128.
OCR2A = 250; // 2 ms.
TCNT2 = 0; // Clear counter.
bitSet(TIFR2,OCF2A);
bitSet(TIMSK2,OCIE2A);
}
void setup(void)
{
lcd.init();
lcd.backlight();
lcd.print("Essai codeur");
delay(500);
pinMode(pin_sw,INPUT_PULLUP);
pinMode(pin_a,INPUT_PULLUP);
pinMode(pin_b,INPUT_PULLUP);
state = 0;
state_sub = 0;
counter = 0;
flag = false;
PCMSK0 = 0x1c;
bitSet(PCIFR,PCIF0); // Clear pending interrupts.
bitSet(PCICR,PCIE0); // Enable PCINT0-7.
lcd.clear();
lcd.print("Valeur : ");
}
void loop()
{
if (flagbtn & 1)
{
lcd.blink();
if (counter)
{
valeur += counter*5;
counter = 0;
if (valeur>255) valeur=255;
if (valeur<0) valeur=0;
lcd.setCursor(9,0);
lcd.print(" ");
lcd.setCursor(9,0);
lcd.print(valeur);
}
}
else
{
counter = 0;
lcd.noBlink();
}
analogWrite(pin_out,valeur);
}
Ce code, compilé avec une version inférieure à 1.6.0 fonctionne comme attendu, à savoir quand j'appuie sur le bouton du codeur, le curseur clignote sur le LCD et je peux modifier la valeur affichée, et quand je re-appuie à nouveau sur le bouton, je quitte l'édition et donc tourner le codeur ne change plus ma variable. Parfait.
La sortie en PWM fonctionne également, tout va bien.
Maintenant je compile ce code avec la version 1.6.0... et je ne comprends plus. Le début semble fonctionner pareil, mais une fois dans l'édition de la valeur, impossible d'en sortir, les appuis suivants sur le bouton ne sont plus pris en compte (alors que la rotation du codeur fonctionne ! )
Mon problème étant que je suis obligé d'utiliser la version 1.6.0 car avec une version antérieure, ma librairies YASM pour les machines à états à base de pointeurs de fonction ne fonctionne pas à cause d'options différentes lors de l'appel du compilateur (du moins si j'ai bien compris). Et je ne peux pas non plus utiliser une version plus récente car alors c'est la librairie pour piloter mon LCD en I2C qui ne fonctionne plus...