Hello
I made an audio amplifier, witch use an arduino nano for driving a volume digital pot (PGA2310), a LCD display, an a digital encodeur with push button.
A long press (>3 s) on the encodeur push button, the ampli turn on, or turn off. A short press on it change the input line. Turn right or left the encodeur increase or decrease the volume.
The LCD display the input fonction and gain.
I use attachinterupt for the encodeur, and SPI for the digital pot.
The problem here is when the the void digitalpot() for SPI transaction is called, the program freeze...
If the void digitalpot() is disabled, the program run normaly (but of course no instruction for the digital pot).
I use in the past a similar program for an another project, with a standalone Atmega328P, and this one run normaly.
Someone can detect an error in this program?
Thanks
#include <SPI.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5);
const int IN3 = 6; // pin commande relai IN3 (1 sur schéma)
const int IN2 = 5; // pin commande relai IN2
const int IN1 = 4; // pin commande relai IN1 (3 sur schéma)
const int INBLT = 7; // pin commande relai IN1
const int CodA = 3; // pin A encodeur
const int CodB = 2; // pin B encodeur
const int BS = 10; // pin bouton select encodeur
const int ChipSelectPin = 9; // PIN SELECT PGA2310
const int ALIM = 8; // pin controle ALIM
int npot = 0 ;
int gain = 0;
long unsigned tempsA ;
long unsigned tempsB; //codeur B (ON/OFF ou chgt affichage)
bool etatA = 0 ;
bool dernierEtatA = 0 ;
bool etatBS = 0 ;
bool dernieretatBS = 0 ;
boolean relai = 0; // état du relais de commande de l'alim
boolean relaiIN1 = 0; // état du relais IN1
boolean relaiIN2 = 0; // état du relais IN2
boolean relaiIN3 = 0; // état du relais IN3
boolean relaiBLT = 0; // état du relais IN4
byte affich ; // défini l'entrée d'affichage
enum : byte {ampli_OFF, ampli_ON} etat_ampli;
void setup() {
etat_ampli = ampli_OFF;
SPI.begin();
lcd.begin(16, 2);
lcd.clear();
pinMode(ChipSelectPin, OUTPUT);
pinMode(BS, INPUT);
pinMode(CodA, INPUT);
pinMode(CodB, INPUT);
pinMode(ALIM, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(INBLT, OUTPUT);
}
void loop() {
attachInterrupt(digitalPinToInterrupt(CodA), codeur, CHANGE);
int gain = (31.5 - (0.5 * (255 - npot))); // transpose valeur niveau volume binaire en dB
etatBS = digitalRead(BS);
if ((etatBS) == 1 && (dernieretatBS) == 0) {
tempsB = millis();
}
if ((etatBS) == 0 && (dernieretatBS) == 1 && (relai == 1)) {
affich++; if (affich > 3) {
affich = 0;
}
}
delay(20);
if ((etatBS == HIGH) && (dernieretatBS == HIGH)) { //teste si bouton resté enfoncé
if ((millis() - tempsB) > 3000) { //teste durée d'appui
lcd.clear();
switch (etat_ampli) {
case ampli_OFF:
while (etatBS == 1) {
etatBS = digitalRead(BS);
lcd.setCursor(0, 0);
lcd.print(" ARGO ON ");
lcd.setCursor(64, 0);
lcd.print(" ");
}
delay(1000);
relai = 1; digitalWrite(ALIM, relai);
etat_ampli = ampli_ON;
break;
case ampli_ON:
while (etatBS == 1) {
etatBS = digitalRead(BS);
lcd.setCursor(0, 0);
lcd.print(" ARGO OFF ");
lcd.setCursor(64, 0);
lcd.print(" ");
}
delay(1000);
relai = 0; digitalWrite(ALIM, relai);
etat_ampli = ampli_OFF;
break;
affich--; if (affich < 0) {
affich = 0;
}
}
}
}
dernieretatBS = etatBS;
if (relai == 0) {
lcd.clear();
relaiIN1 = 0;
relaiIN2 = 0;
relaiIN3 = 0;
relaiBLT = 0;
digitalWrite(IN1, relaiIN1);
digitalWrite(IN2, relaiIN2);
digitalWrite(IN3, relaiIN3);
digitalWrite(INBLT, relaiBLT);
}
if (relai == 1) {
if (affich == 0) {
lcd.setCursor(0, 0);
lcd.print(" input 1 ");
char tampon[16] = "";
sprintf(tampon, "%s%3d%s", " gain ", gain, " dB ");
lcd.setCursor(64, 0);
lcd.print(tampon);
relaiBLT = 0; digitalWrite(INBLT, relaiBLT);
relaiIN1 = 1; digitalWrite(IN1, relaiIN1);
relaiIN2 = 0; digitalWrite(IN2, relaiIN2);
relaiIN3 = 0; digitalWrite(IN3, relaiIN3);
}
if (affich == 1) {
lcd.setCursor(0, 0);
lcd.print(" input 2 ");
lcd.setCursor(64, 0);
char tampon[16] = "";
sprintf(tampon, "%s%3d%s", " gain ", gain, " dB ");
lcd.print(tampon);
relaiIN1 = 0; digitalWrite(IN1, relaiIN1);
relaiIN2 = 1; digitalWrite(IN2, relaiIN2);
relaiIN3 = 0; digitalWrite(IN3, relaiIN3);
relaiBLT = 0; digitalWrite(INBLT, relaiBLT);
}
if (affich == 2) {
lcd.setCursor(0, 0);
lcd.print(" input 3 ");
lcd.setCursor(64, 0);
char tampon[16] = "";
sprintf(tampon, "%s%3d%s", " gain ", gain, " dB ");
lcd.print(tampon);
relaiIN1 = 0; digitalWrite(IN1, relaiIN1);
relaiIN2 = 0; digitalWrite(IN2, relaiIN2);
relaiIN3 = 1; digitalWrite(IN3, relaiIN3);
relaiBLT = 0; digitalWrite(INBLT, relaiBLT);
}
if (affich == 3) {
lcd.setCursor(0, 0);
lcd.print(" Bluetooth ");
lcd.setCursor(64, 0);
char tampon[16] = "";
sprintf(tampon, "%s%3d%s", " gain ", gain, " dB ");
lcd.print(tampon);
relaiIN1 = 0; digitalWrite(IN1, relaiIN1);
relaiIN2 = 0; digitalWrite(IN2, relaiIN2);
relaiIN3 = 0; digitalWrite(IN3, relaiIN3);
relaiBLT = 1; digitalWrite(INBLT, relaiBLT);
}
}
}
void codeur() {
if (relai == 1) {
etatA = digitalRead(CodA);
if ( etatA != dernierEtatA ) {
if ( abs(millis() - tempsA) > 20 ) { // anti rebond
if (digitalRead(CodB) != dernierEtatA) { // Si B different de l'ancien état de A alors sens anti horaire
npot--; if (npot < 0) {
npot = 0;
}
}
else { // sinon sens horaire
npot++; if (npot > 256) {
npot = 256; // incrémentation niveau pot
}
}
tempsA = millis(); // memorisation du temps pour A
}
dernierEtatA = etatA ;// memorisation de l'état de A
digitalPot(npot);
delay(10);
}
}
}
void digitalPot(int npot) {
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
digitalWrite(ChipSelectPin, LOW);
SPI.transfer(npot);//pot left
SPI.transfer(npot);//pot right
digitalWrite(ChipSelectPin, HIGH);
SPI.endTransaction();
}