/**************************************************************************
Base sistema diagnostico per Arduino Uno
- l'originale si basa su pinchange interrupt, presente ma non abilitato in questo codice
- a partire dalla versione 000 si procederà con l'implementare tutti i controlli, poi si
tornerà a ristabilire il pinchange interrupt
Questo programma è stato scritto nel modo più semplice
possibile allo scopo di non richiedere un'eccellente
conoscenza del linguaggio e consentire di essere provato
AS IS sul simulatore wokwi
Per nessun motivo la pubblicazione di questo codice
responsabilizza gli autori e tantomeno li obbliga a
fornire supporto e/o qualsiasi spiegazione o chiarimento
sebbene, condizioni permettendo, si cercherà di rispondere
ad eventuali domande, senza alcun obbligo e/o impegno e/o
responsabilità
.........................................................
Frase Copyright da riportare sempre in forma completa :
"Può essere utilizzato a qualsiasi scopo sotto la propria
totale, completa ed esclusiva responsabilità.
Chiunque potra' modificarlo ed adattarlo alle proprie
esigenze riportando sempre ed in toto la presente
'Frase Copyright' , anche a valle di profonde modifiche.
Tratto da https://www.facebook.com/groups/883620498953478 "
.....................
NOTE l'utilizzo di portB_flag garantisce un deboucing
infatti un impulso molto breve non viene visualizzato
sul monitor
**************************************************************************/
#include <Wire.h> // protocollo i2c per settare ad esempio la velocità
#include <Adafruit_GFX.h> // font
#include <Adafruit_SSD1306.h>
#include <stdio.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
volatile Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// parola di stato dei 6 LSB bit della porta B
volatile byte portB_state=B00000000;
volatile byte portB_flag=false;
volatile byte least_one=false;
byte portB_oldstate=B00000000;
//long start_mm, dtime;
int start_h=17, start_m=59, clk=53;
char *outstr;
char ch,outstr1[30];
void setup() {
int i;
outstr=&(outstr1[0]); // esercizio sui puntatori
Serial.begin(9600);
//Wire.begin();
//Wire.setClock(400000L); // velocità dell' i2c
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.cp437(true); // Use full 256 char 'Code Page 437' font
// Clear the buffer
display.clearDisplay();
display.display();
start_h=23;
start_m=59;
clk=56;
// portB_state=B00000000;
// PCICR |= B00000001; //Bit0 = 1 -> "PCIE0" enabeled (PCINT8 to PCINT13)
// PCMSK0 |= B00111111;
}
void write_list (void)
{ /* questa funzione scrive le "8" righe che terminano con OUTmode */
display.setTextColor(SSD1306_WHITE);
for (int i=0;i<6;i++)
{ display.setCursor(0,(i+1)*8);
sprintf(outstr,"%2d ",i+1);
display.print(outstr);
}
for (int i=0;i<68;i+=6)
{ display.setCursor(i+36,48);
sprintf(outstr,"%1d",(i/6)%10);
display.print(outstr);
}
sprintf(outstr,"chanel");
display.setTextColor(SSD1306_WHITE);
display.setCursor(48,40);
display.print(outstr);
sprintf(outstr,"%c",219);
display.setTextColor(SSD1306_WHITE);
display.setCursor(36,56);
display.print(outstr);
display.display();
}
void pseudo_clock(void)
{ /* questa funzione simula la stampa dell'orario corrente nella prima riga */
// cancella orario precedete
display.setCursor(76, 0);
display.setTextColor(SSD1306_BLACK);
sprintf(outstr,"%02d:%02d:%02d",start_h,start_m,clk);
display.print(outstr);
// cambio del minuto
if(clk==59) {
// cambio dell'ora
if(start_m==59){
if(start_h==23) start_h=0;
else start_h++;
start_m=-1;
}
start_m++;
clk=-1;
}
// incremento dei secondi
clk++;
// stampa nuovo orario
display.setCursor(76, 0);
display.setTextColor(SSD1306_WHITE);
sprintf(outstr,"%02d:%02d:%02d",start_h,start_m,clk);
display.print(outstr);
display.display();
}
int chanel_flag=1;
void loop()
{
static long now,last,analog_start;
static int flag13=false,i,test=2,a_value[4]={0,0,0,0},a_oldvalue[4]={0,0,0,0};
// simulatore RTC
now=millis(); // sostituire con timer di 1 sec
if( (now-last) > 500L) {
pseudo_clock();
//chanel_flag=1; // timer ogni 333ms
last=now;
}
switch(test)
{ case 1: // test degli output
/* tutte le porte tranne i2c, RX, TX vengono fatte blinkerare 5 volte
la porta 13 viene tenuta bassa sino a fine ciclo, quando viene
portata alta, eccita il relay che porta in conduzione i potenzionemtri
*/
display.setCursor(0,0);
display.write("START");
display.setCursor(32,16);
display.write("OUTPUT TEST");
display.display();
// inizializzo le porte come uscite, tranne i2C, RX e TX
for(i=2;i<18;i++) pinMode(i, OUTPUT);
PORTB &= B11011111; flag13=false;
for(i=0;i<5;i++)
{ // farlo diventare passante per il clock ?
PORTB |= B00011111;
PORTC |= B00001111;
PORTD |= B11111100;
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(12,36);
display.write("ooooo oooooo oooo");
display.display();
if(i==1)
{ display.setTextColor(SSD1306_BLACK);
display.setCursor(0,0);
display.write("START");
}
delay(200);
PORTB &= B11000000;
PORTC &= B11110000;
PORTD &= B00000011;
display.setTextColor(SSD1306_BLACK); // Draw white text
display.setCursor(12,36);
display.write("ooooo oooooo oooo");
display.display();
delay(400);
last=now; pseudo_clock();
}
test++;
break;
case 2: // initialize test degli output
PORTB |= B00100000; // P13 ON - relay ON
flag13=true; // we need it because wokwi have an error
display.clearDisplay();
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(24,12);
display.write("TEST ANALOG IN");
display.display();
analog_start=now;
test++;
break;
case 3: //
if(!flag13) // we need it because wokwi have an error
{ test++;
PORTB &= B11011111; // P13 Off
flag13=false;
delay(500);
display.clearDisplay();
break;
}
analogRead(A0); a_value[0]=analogRead(A0);
analogRead(A1); a_value[1]=analogRead(A1);
analogRead(A2); a_value[2]=analogRead(A2);
analogRead(A3); a_value[3]=analogRead(A3);
if(a_value[0]!=a_oldvalue[0] ||
a_value[1]!=a_oldvalue[1] ||
a_value[2]!=a_oldvalue[2] ||
a_value[3]!=a_oldvalue[3] )
{
for(i=0;i<4;i++)
{ display.setCursor(8,20+(i+1)*8);
display.setTextColor(SSD1306_BLACK); // Draw white text
sprintf(outstr,"A(%d)=%04d;",i+1,a_oldvalue[i]);
display.print(outstr);
display.display();
display.setCursor(8,20+(i+1)*8);
display.setTextColor(SSD1306_WHITE); // Draw white text
sprintf(outstr,"A(%d)=%04d;",i+1,a_value[i]);
display.print(outstr);
display.display();
}
a_oldvalue[0]=a_value[0];
a_oldvalue[1]=a_value[1];
a_oldvalue[2]=a_value[2];
a_oldvalue[3]=a_value[3];
analog_start=now;
}
if((now-analog_start)>5000)
{ test++;
PORTB &= B11011111; // P13 Off
flag13=false; // we need it because wokwi have an error
display.clearDisplay();
}
break;
case 4: //
test++;
break;
case 5: //
test++;
break;
case 6: //
test++;
break;
default:
break;
}
}
#if 0
void loop()
{
static long now,last;
static int k=3;
int num;
static int chanel=0, old_chanel;
// K va inizializzato con l'unità in secondi dello start
//PORTD |=0b00111111;
num=6-int(log10(portB_state>>2)/log10(2)+0.01);
//se è cambiata la parola di stato;
if(portB_flag || least_one)
{
least_one=false;
/*
// stampa il codice numerico della parola di stato
display.setTextColor(SSD1306_BLACK);
display.setCursor(104,0);
sprintf(outstr,"%3d",6-int(log10(portB_state>>2)/log10(2)+0.01));
display.print(outstr);
display.setTextColor(SSD1306_WHITE);
display.setCursor(104,0);
sprintf(outstr,"%3d",num);
display.print(outstr);
*/
// stampa un quadratino sull'ultima colonna
// per memorizzare l'ultimo tasto premuto
// +0.01 serve a compensare un errore di log10()
sprintf(outstr,"%c",219);
display.setTextColor(SSD1306_BLACK);
display.setCursor(20,(6-int(log10(portB_state>>2)/log10(2)+0.01))*8);
display.print(outstr);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20,num*8);
display.print(outstr);
if(chanel_flag)
{
switch(num)
{
case 5:
chanel_flag=0;
sprintf(outstr,"%c",219);
display.setTextColor(SSD1306_BLACK);
display.setCursor(chanel*6+36,56);
display.print(outstr);
chanel--;
if(chanel<0)chanel=0;
display.setTextColor(SSD1306_WHITE);
display.setCursor(chanel*6+36,56);
display.print(outstr);
break;
case 6:
chanel_flag=0;
sprintf(outstr,"%c",219);
display.setTextColor(SSD1306_BLACK);
display.setCursor(chanel*6+36,56);
display.print(outstr);
chanel++;
if(chanel>11)chanel=11;
display.setTextColor(SSD1306_WHITE);
display.setCursor(chanel*6+36,56);
display.print(outstr);
break;
default:
break;
}
}
}
else
{ chanel_flag=1;
/*
// stampa il codice numerico della parola di stato
display.setTextColor(SSD1306_BLACK);
display.setCursor(104,0);
sprintf(outstr,"%3d",num);
display.print(outstr);
*/
// stampa un quadratino sull'ultima colonna
// per memorizzare l'ultimo tasto premuto
// +0.01 serve a compensare un errore di log10()
sprintf(outstr,"%c",219);
display.setTextColor(SSD1306_BLACK);
display.setCursor(20,num*8);
display.print(outstr);
}
display.display();
portB_oldstate=portB_state;
// simulatore RTC
now=millis(); // sostituire con timer di 1 sec
if( (now-last) > 500L) {
clock();
//chanel_flag=1; // timer ogni 333ms
last=now;
k++;
}
}
#endif