Se connecter
Se connecter

ou
Créer un compte

ou
Sujet de la discussion Realisation D'un Controleur Midi Style Arc MONOME 2 (Coup de Pouce pour Programmation)
Salut a tous

Toujours dans l'aventure de création de contrôleur Midi Personnalisé
J'ai fabriqué des cercles de Led contrôler par 4 registre a décalage 74HC595
ces cercle intégreront un step sequencer par la suite.

Pour le programme je me suis servi de celui ci car il correspond aux animations de Led que je voudrai obtenir

https://oleg31337.blogspot.com/2013/09/rotary-encoder-visualization-using-595.html

 boolean bitA, bitB, obitA, obitB; // variables used for encoder movement detection
byte enc = 0, oenc = 0; // current encoder value and old one
int encpos = 1; // position of current led from 0 to 16
int incr = 0; // used in rotation
byte encpinA = 2, encpinB = 3; // pins of arduino to which encoder is connected
byte latchPin = 10, dataPin = 11, clockPin = 12; // controlling 595 shift registers
unsigned long prevtime = 0; // rotation is time bound so I use long integers
int spd=15; // position in array of speeds which represent 0 speed
int rspeed [31] = {-2,-3,-4,-5,-7,-10,-15,-23,-34,-51,-77,-115,-173,-259,-389,0,389,259,173,115,77,51,34,23,15,10,7,5,4,3,2}; // this is an array of rotation speed constants
byte b1pin=5, b2pin=6;
boolean b1state=0, b2state=0, bb=0; // this is for handling button presses
int mode=0; // mode of operation

void setup() {
  Serial.begin(9600); // Serial Port for debugging
  pinMode(encpinA, INPUT); // initializing encoder pins
  pinMode(encpinB, INPUT);
  pinMode(latchPin, OUTPUT); // initializing 595 registers pins
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  digitalWrite(encpinA,HIGH); // I use pull-up resistors for encoder pins
  digitalWrite(encpinB,HIGH);
  pinMode(b1pin, INPUT); // two buttons to control mode of operation
  pinMode(b2pin, INPUT);
  digitalWrite(b1pin,HIGH); //internal pull-ups are used for buttons too
  digitalWrite(b2pin,HIGH); 

  led_reset(); // resetting all to defaults
}

void loop() {
  //this is all about rotary encoder movement
  bitA = digitalRead(encpinA);
  bitB = digitalRead(encpinB);
  if (bitA != obitA || bitB != obitB){
    enc = bitA;
    enc = enc << 1;
    enc = enc | bitB;
    if (oenc==1 && enc==3 || oenc==3 && enc==2 || oenc==2 && enc==0 || oenc==0 && enc==1) {incr=1;}
    else {incr=-1;}
    if (mode==0){led_dot(incr);}
    if (mode==1){led_fill(incr);}
    if (mode==2){led_rotate(incr);}
    incr = 0;
    oenc=enc;
    obitA = bitA;
    obitB = bitB;
  }
  if (mode==2){  led_rotate(incr);}
  bb = button1();
  if (bb == 0) { selectmode(-1);}
  bb = button2();
  if (bb == 0) { selectmode(1);}
}

void selectmode (int change) // subroutine to chose mode of operation
  {
    mode = mode + change;
    if (mode > 2) { mode = 2; }
    if (mode < 0) { mode = 0; }
    Serial.print("mode:");
    Serial.println(mode,DEC);
    led_reset();
  }
  
void led_rotate(int incr) { // rotating leds with certain speed, knob controls speed of rotation
  unsigned long curtime = millis();
  if (incr > 0) {spd++;}
  if (incr < 0) {spd--;}
  if (spd < 0) {spd = 0;}
  if (spd > 30) {spd = 30;}
  if (curtime - prevtime > abs(rspeed[spd])) {
    prevtime = curtime;
    if (rspeed[spd] > 0) {encpos++;}
    if (rspeed[spd] < 0) {encpos--;}
    if (encpos < 0) {encpos = 15;}
    if (encpos > 15) {encpos = 0;}
    unsigned int outled = 1;
    outled = outled << encpos;
    ledout(outled);
  }
}

void led_fill(int incr) { // filling up leds with rotation like circular bar graph
  unsigned int outled = 0;
  encpos = encpos + incr;
  if (encpos < 0) {encpos = 0;}
  if (encpos > 16) {encpos = 16;}
  for (int i=1; i<=encpos; i++){
    outled = outled << 1;
    outled = outled | 1;
  }
  ledout(outled);
}

void led_dot(int incr) { // led dot is rotating with knob
  unsigned int outled = 1;
  encpos = encpos + incr;
  if (encpos < 0) {encpos = 15;}
  if (encpos > 15) {encpos = 0;}
  outled = outled << encpos;
  ledout(outled);
}

void led_reset() { // resetting all leds to low state
  encpos = 0;
  incr = 0;
  spd=15;
  unsigned int outled = 0;
  digitalWrite(latchPin, LOW);
  ledout(outled);
}

void ledout(unsigned int outled) { // subroutine to shift-out data to 595 chips
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, outled);
  shiftOut(dataPin, clockPin, MSBFIRST, (outled>>8));
  digitalWrite(latchPin, HIGH);
}
int button1 () // button1 control
  {
    boolean b1 = digitalRead(b1pin);
    if (b1 == 0 && b1state == 0) { b1state=1; return 0; }
    if (b1 == 1) { b1state=0; return 1; }
    if (b1 == 0 && b1state == 0) { return 1; }
    return 1;
  }

int button2 () // button2 control
  {
    boolean b2 = digitalRead(b2pin);
    if (b2 == 0 && b2state == 0) { b2state=1; return 0; }
    if (b2 == 1) { b2state=0; return 1; }
    if (b2 == 0 && b2state == 0) { return 1; }
    return 1;
  }


J'ai fait quelque test comme on peut le voir sur la video


Mon programme Arduino :


 boolean bitA, bitB, obitA, obitB; // variables used for encoder movement detection
byte enc = 0, oenc = 0; // current encoder value and old one
int encpos = 1; // position of current led from 0 to 16
int incr = 0; // used in rotation
byte encpinA = 2, encpinB = 4; // pins of arduino to which encoder is connected
byte latchPin = 5, dataPin = 7, clockPin = 6; // controlling 595 shift registers
unsigned long prevtime = 0; // rotation is time bound so I use long integers
int spd=15; // position in array of speeds which represent 0 speed
int rspeed [31] = {-2,-3,-4,-5,-7,-10,-15,-23,-34,-51,-77,-115,-173,-259,-389,0,389,259,173,115,77,51,34,23,15,10,7,5,4,3,2}; // this is an array of rotation speed constants
byte b1pin=3, b2pin=9;
boolean b1state=0, b2state=0, bb=0; // this is for handling button presses
int mode=0; // mode of operation

void setup() 
{
  Serial.begin(9600); // Serial Port for debugging
  pinMode(encpinA, INPUT); // initializing encoder pins
  pinMode(encpinB, INPUT);
  pinMode(latchPin, OUTPUT); // initializing 595 registers pins
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  digitalWrite(encpinA,HIGH); // I use pull-up resistors for encoder pins
  digitalWrite(encpinB,HIGH);
  pinMode(b1pin, INPUT); // two buttons to control mode of operation
  pinMode(b2pin, INPUT);
  digitalWrite(b1pin,HIGH); //internal pull-ups are used for buttons too
  digitalWrite(b2pin,HIGH); 
  led_reset(); // resetting all to defaults
}

void loop() 
{
  //this is all about rotary encoder movement
     bitA = digitalRead(encpinA);
  bitB = digitalRead(encpinB);
  
  if (bitA != obitA || bitB != obitB)
  {
    enc = bitA;
    enc = enc << 1;
    enc = enc | bitB;
    if (oenc==1 && enc==3 || oenc==3 && enc==2 || oenc==2 && enc==0 || oenc==0 && enc==1) 
    {
      incr=1;
    }
    else {
      incr=-1;
      }
    if (mode==0){led_dot(incr);}
    if (mode==1){led_fill(incr);}
    if (mode==2){led_rotate(incr);}
    incr = 0;
    oenc=enc;
    obitA = bitA;
    obitB = bitB;
  }
  if (mode==2){  led_rotate(incr);}
  bb = button1();
  if (bb == 0) { selectmode(-1);}
  bb = button2();
  if (bb == 0) { selectmode(1);
  }
}
void selectmode (int change) // subroutine to chose mode of operation
  {
    mode = mode + change;
    if (mode > 2) { mode = 2; }
    if (mode < 0) { mode = 0; }
    Serial.print("mode:");
    Serial.println(mode,DEC);
    led_reset();
  }
  
void led_rotate(int incr) { // rotating leds with certain speed, knob controls speed of rotation
  unsigned long curtime = millis();
  if (incr > 0) {spd++;}
  if (incr < 0) {spd--;}
  if (spd < 0) {spd = 0;}
  if (spd > 30) {spd = 30;}
  if (curtime - prevtime > abs(rspeed[spd])) {
    prevtime = curtime;
    if (rspeed[spd] > 0) {encpos++;}
    if (rspeed[spd] < 0) {encpos--;}
    if (encpos < 0) {encpos = 15;}
    if (encpos > 15) {encpos = 0;}
    unsigned int outled = 1;
    outled = outled << encpos;
    ledout(outled);
  }
}

void led_fill(int incr)
{ // filling up leds with rotation like circular bar graph
  unsigned int outled = 0;
  encpos = encpos + incr;
  if (encpos < 0) {
    encpos = 0;
    }
  if (encpos > 32) 
  {
    encpos = 32;
    }
  for (int i=1; i<=encpos; i++)
  {
    outled = outled << 1;
    outled = outled | 1;
  }
  ledout(outled);
}

void led_dot(int incr) 
{ // led dot is rotating with knob
  unsigned int outled = 1;
  encpos = encpos + incr;
  
  if (encpos < 0) {encpos = 30;}
  if (encpos > 30) {encpos = 0;}
  outled = outled << encpos;
  ledout(outled);
}

void led_reset() 
{ // resetting all leds to low state
  encpos = 0;
  incr = 0;
  spd=15;
  unsigned int outled = 0;
  digitalWrite(latchPin, LOW);
  ledout(outled);
}

void ledout(unsigned int outled) { // subroutine to shift-out data to 595 chips
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, outled);
  shiftOut(dataPin, clockPin, MSBFIRST, (outled>>8));
  digitalWrite(latchPin, HIGH);
}
int button1 () // button1 control
  {
    boolean b1 = digitalRead(b1pin);
    if (b1 == 0 && b1state == 0) { b1state=1; return 0; }
    if (b1 == 1) { b1state=0; return 1; }
    if (b1 == 0 && b1state == 0) { return 1; }
    return 1;
  }

int button2 () // button2 control
  {
    boolean b2 = digitalRead(b2pin);
    if (b2 == 0 && b2state == 0) { b2state=1; return 0; }
    if (b2 == 1) { b2state=0; return 1; }
    if (b2 == 0 && b2state == 0) { return 1; }
    return 1;
  }


Le probleme est que je ne peux faire une animation de led que dans un seul sens
L'animation ne suit pas le sens de rotation de l'encoder.
Or dans la video ou le test du programme d'origine est effectué nous voyons bien que c'est le cas


J'ai tester plein de manipulation au niveau du programme en regardant comment fonctionne un encoder rotatif
Surtout pour la detection du sens de rotation.

Qui se fait ici il me semble ;

if (bitA != obitA || bitB != obitB)
  {
    enc = bitA;
    enc = enc << 1;
    enc = enc | bitB;
    if (oenc==1 && enc==3 || oenc==3 && enc==2 || oenc==2 && enc==0 || oenc==0 && enc==1) 
    {
      incr=1;
    }
    else {
      incr=-1;
      }


Mais je coince pour incrementer et decrementer les leds en fonctions du sens de rotation de mon Rotary Encoder

Merci d'avance pour le coup de main ou tout autres pistes que me seraient utiles
2
Bon premièrement j'ai fait un erreur en inversant Clock Pin et Latch Pin :face_with_raised_eyebrow:

En rectifiant le programme fonctionne mais en 2 x 15 leds en obtenant le bon sens de rotation du rotary encoder :thinking:
Comme si il y avait 2 x 2 hc595 en series

Effectivement l'usage des bibliothèques simplifie les choses

J'ai installé la bibliothèque du rotary encoder

/* Encoder Library - TwoKnobs Example
 * [url]https://www.pjrc.com/teensy/td_libs_Encoder.html[/url]
 *
 * This example code is in the public domain.
 */

#include <Encoder.h>

// Change these pin numbers to the pins connected to your encoder.
//   Best Performance: both pins have interrupt capability
//   Good Performance: only the first pin has interrupt capability
//   Low Performance:  neither pin has interrupt capability
Encoder knob(2, 4);

//   avoid using pins with LEDs attached

void setup() {
  Serial.begin(9600);
  Serial.println("TwoKnobs Encoder Test:");
}

long position = -999;


void loop() {
  long newknob;
  newknob = knob.read();
 
  if (newknob != position || newknob != position)
  {
    Serial.print("Left = ");
    Serial.print(newknob);
     Serial.println();
    position = newknob;
    
  }
  // if a character is sent from the serial monitor,
  // reset both back to zero.
  if (Serial.available()) {
    Serial.read();
    Serial.println("Reset both knobs to zero");
    knob.write(0);
  
  }
}


4131345.png


Je détecte bien la position de mon encoder

Il existe aussi des bibliothèques pour le registre a décalage
Avec le programme si dessous j'obtiens un chenillard
Donc aucun problème de connexions des mes shift register

#include <HC595.h>

const int chipCount = 4;  // Number of serialy connected 74HC595 (8 maximum)
const int latchPin = 6;  // Pin ST_CP (12) of the 74HC595-Latch
const int clockPin = 5;  // Pin SH_CP (11) of the 74HC595-Clock
const int dataPin = 7;   // Pin DS (14) of the 74HC595-Data In

//Constructor
HC595 ledArray(chipCount,latchPin,clockPin,dataPin);

int delayMs = 100 ;
int lastPin = ledArray.lastPin();

void setup() {
  ledArray.reset();
}

void loop() {
  for (int i = 0 ; i <= lastPin ; i++) {
    ledArray.setPin(i, ON);
    delay(delayMs);
  }
  for (int i = lastPin ; i >= 0 ; i--) {
    ledArray.setPin(i, OFF);
    delay(delayMs);
  }
  for (int i = lastPin ; i >= 0 ; i--) {
    ledArray.setPin(i, TOGGLE);
    delay(delayMs);
  }
  for (int i = 0 ; i <= lastPin ; i++) {
    ledArray.setPin(i, TOGGLE);
    delay(delayMs);
  }
}


[ Dernière édition du message le 31/12/2021 à 10:18:52 ]

3
Mon programme prend que 2 shift register en considération
soit 16 bits (2 x 16 bits)
Est ce qu'il y a un moyen de préciser dans le programme que je désire 32 bits?
void ledout(unsigned int outled) { // subroutine to shift-out data to 595 chips
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, outled);
  shiftOut(dataPin, clockPin, MSBFIRST, (outled>>8));
  digitalWrite(latchPin, HIGH);
}

[ Dernière édition du message le 04/01/2022 à 09:17:45 ]