/* 2024 02 22 19:00
versione con comando >down< longclick
derivante dalla 007
l'opzione viene impostata con questi due parametri
#define timeout 3000
#define LongPressed 1000
NOTA per tutti i comandi
un click si considera eseguito quando viene lasciato il pulsante
o quando cambia il comando obd
NOTA per l'autore del codice
nel codice vanno ripuliti e gestiti meglio gli old_command
*/
#include <mcp_can.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//SSD1306
#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)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO: A4(SDA), A5(SCL)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define SXC 1
#define DXC 2
#define HBK 3 // half blink
#define STC 4 // Stop
#define DWC 5 // Down
#define LDC 6 // DOWN prolungato
#define FBK 7 // full blink
#define WTC 8 // Wait command
#define NTD 11 // not defined
#define DEF 12 // defined
#define FDW 14 // first_down
#define DEBUG 0
/*
look well look well look well look well look well
se sei su wokwi devi commentare la riga 18 con #define MCP2515
esempio: // #define MCP2515
se stai usando la scheda MCP2515 allora non la devi commentare
esempio: #define MCP2515
*/
//#define MCP2515
//buffer
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
// MCP CS on SPI SS
MCP_CAN CAN0(10);
// INPUT
#define INPUT 2
const byte btndx[] = {0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}; //comando freccia destra
const byte btnsx[] = {0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}; //comando freccia sinistra
const byte btnce[] = {0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}; //comando centro disattiva frecce
const byte btndn[] = {0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00}; //comando 4 frecce
// light
#define RELDX 9
#define RELSX 8
int command, old_command, tmp_command; // command from OBD or switches
// blink
bool flag_sx,flag_dx;
unsigned long clock, time,old_time;
#define blink_semiperiod 300
// autostop
bool autostop_flag;
unsigned long AS_time,AS_old_time;
#define AS_time_elapsed 6000 // auto spegnimento half blink
// full blink
int full_blink_status; // 0 off, 1 full blin waiting , 2 full blink ON
unsigned long L_time,L_old_time, LP_time;
#define timeout 2000
#define LongPressed 1000
void setup()
{
Serial.begin(115200);
#ifdef MCP2515
if(CAN0.begin(MCP_STDEXT, CAN_500KBPS, MCP_8MHZ) == CAN_OK) Serial.print("MCP2515 Init Okay!!\r\n");
else Serial.print("MCP2515 Init Failed!!\r\n");
#endif
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
pinMode(INPUT, INPUT); // Setting pin 2 for /INT input
pinMode(RELDX, OUTPUT);
pinMode(RELSX, OUTPUT);
digitalWrite(RELDX, HIGH); //rele su spento
digitalWrite(RELSX, HIGH); // rele su spento
CAN0.setMode(MCP_NORMAL); // Change to normal mode to allow messages to be transmitted
display.display();//addedd
display.setTextColor(WHITE);//added
display.clearDisplay();//addedd
display.setCursor(115, 0);//addedd
display.println("ON");//addedd
display.setCursor(0, 10);//addedd
display.println("MSG:");
display.setCursor(0, 20);//addedd
display.println("LST:");//addedd
display.setCursor(80, 30);//addedd
display.println("10:12:23");//addedd
display.display();
digitalWrite(RELDX, HIGH);
digitalWrite(RELSX, HIGH);
flag_dx=LOW;
flag_sx=LOW;
autostop_flag=LOW;
AS_old_time=0;
old_time=0;
full_blink_status=0;
L_old_time=0;
display.setCursor(26, 10); display.println("WELCOME");//addedd
display.setCursor(26, 20); display.println(" MKSTM");//addedd
display.display();
command=WTC; old_command=NTD;
}
bool live=false;
void loop()
{ clock=millis();
#if DEBUG
display.setCursor(0, 0);
live=!live;
if(live) display.println("*");//addedd
else display.println(" ");//addedd
#endif
// lcd.print(" ");lcd.print(command);lcd.print(" ");lcd.print(old_command);
// autostop del simpleblinking
// funziona quasi come un timer del MCU quindi deve rimanere fuori
// dallo switch
if(autostop_flag)
{ AS_time=clock;
if( (AS_time-AS_old_time) > AS_time_elapsed)
{ command=STC; old_command=NTD;
display.setCursor(26, 20);
display.println(" HB end ");//addedd
// delay(300); // serve?
} }
//#if LONG_PRESSED
// long time timeout
// funziona quasi come un timer del MCU quindi deve rimanere fuori
// dallo switch
if(full_blink_status==1 )
{ L_time=clock;
if ( (L_time-L_old_time) > timeout )
{ // 300 va calibrato se DW viene alzato presto
// status era stato premuto, ma è passato troppo tempo
display.setCursor(26, 10); display.println(" Time out ");//addedd
display.setCursor(26, 20); display.println(" STOP .");//addedd
full_blink_status=0;
command=WTC; old_command=NTD; // come in setup
delay(200); // bello, ma serve????
display.setCursor(26, 10); display.println(" .");//addedd
} }
//#endif
// status half blink
if (flag_sx)
{ time=clock;
if((time-old_time)>blink_semiperiod)
{ old_time=time;
digitalWrite(RELSX, !digitalRead(RELSX));
} }
if (old_command==SXC) old_command==NTD;
if (flag_dx)
{ time=clock;
if((time-old_time)>blink_semiperiod)
{ old_time=time;
digitalWrite(RELDX, !digitalRead(RELDX));
} }
if (old_command==DXC)
{ old_command==NTD;
}
//#if LONGPRESSED
if (full_blink_status==2)
{ time=clock;
if((time-old_time)>blink_semiperiod)
{ old_time=time;
digitalWrite(RELSX, !digitalRead(RELSX));
digitalWrite(RELDX, !digitalRead(RELDX));
} }
//#endif
// WAIT COMMAND
#ifdef MCP2515
// attendo comando dalla scheda 2515
// se PIN2 viene portato a zero
// prelievo il dato da SPI
if(!digitalRead(2)) CAN0.readMsgBuf(&rxId, &len, rxBuf);
{ if(len==8)
{
if (memcmp(btnsx,rxBuf,len)==0) command=SXC;
if (memcmp(btndx,rxBuf,len)==0) command=DXC;
if (memcmp(btnce,rxBuf,len)==0) command=STC;
if (memcmp(btndn,rxBuf,len)==0) command=DWC;
}
}
if (command==DWC && old_command==NTD)
{ old_command=FDW;
L_old_time=millis();
}
#else
// attendo comando da pulsantiera analogica
if(command==WTC)
{ tmp_command =analogRead(A0);
tmp_command+=analogRead(A1)*2;
tmp_command+=analogRead(A2)*4;
tmp_command+=analogRead(A3)*5;
tmp_command=(int)(tmp_command/1023);
if(tmp_command!=0) command=tmp_command;
if(tmp_command==DWC)
{ old_command=FDW;
L_old_time=millis();
}
while(tmp_command!=0)
{ tmp_command =analogRead(A0);
tmp_command+=analogRead(A1)*2;
tmp_command+=analogRead(A2)*4;
tmp_command+=analogRead(A3)*5;
tmp_command=(int)(tmp_command/1023);
}
#if DEBUG
display.setCursor(1, 0);
display.println("01");//addedd
display.println(command);//addedd
display.println(" ");//addedd
display.println(old_command);//addedd
display.println(" ");//addedd
#endif
}
#endif
if (command==DWC && old_command==FDW) LP_time=millis()-L_old_time;
if (command!=DWC) old_command=DEF;
if(command!=old_command )
{
#if DEBUG
display.setCursor(1, 0); display.println("02");//addedd
#endif
switch (command)
{ case SXC:
#if DEBUG
display.setCursor(1, 0); display.println("03");//addedd
#endif
display.setCursor(26, 10); display.println("03");//addedd
display.setCursor(26, 20); display.println(" Left .");//addedd
digitalWrite(RELSX, LOW);
digitalWrite(RELDX, HIGH);
flag_sx=HIGH;
flag_dx=LOW;
autostop_flag=HIGH;
old_time=millis();
AS_old_time=old_time;
command=WTC; old_command=DEF;
break;
case DXC:
#if DEBUG
display.setCursor(1, 0); display.println("04");//addedd
#endif
display.setCursor(26, 10); display.println(" ");//addedd
display.setCursor(26, 20); display.println(" Right .");//addedd
digitalWrite(RELDX, LOW);
digitalWrite(RELSX, HIGH);
flag_dx=HIGH;
flag_sx=LOW;
autostop_flag=HIGH;
old_time=millis();
AS_old_time=old_time;
command=WTC; old_command=DEF;
break;
case STC:
#if DEBUG
display.setCursor(1, 0); display.println("05");//addedd
#endif
// STOP Command
display.setCursor(26, 10); display.println(" .");//addedd
display.setCursor(26, 20); display.println(" STOP .");//addedd
digitalWrite(RELDX, HIGH); // rele dx spento
digitalWrite(RELSX, HIGH); // rele sx spento
flag_sx=LOW;
flag_dx=LOW;
old_time=0;
AS_old_time=0;
autostop_flag=LOW;
L_old_time=0;
full_blink_status =0;
command=WTC; old_command=STC;
delay(100); // necessario
break;
case DWC:
// DW è stato premuto arriva la prima raffica
if(full_blink_status==0)
{
display.setCursor(26, 10); display.println(" .");//addedd
display.setCursor(26, 20); display.println(" DW Pressed ");//addedd
full_blink_status=1;
}
if(LP_time>LongPressed )
{
digitalWrite(RELDX, LOW);
digitalWrite(RELSX, LOW);
flag_sx=LOW;
flag_dx=LOW;
old_time=millis();
display.setCursor(26, 10); display.println(" .");//addedd
display.setCursor(26, 20); display.println(" Blink .");//addedd
autostop_flag=LOW;
AS_old_time=0;
L_old_time=0;
full_blink_status=2; // blink mode
old_command=NTD;
}
command=WTC; //old_command=DWC;
break;
case LDC:
break;
case WTC:
#if 0
display.setCursor(1, 0); display.println("08");//addedd
if(old_command!=NTD)
{ display.setCursor(26, 10);
display.println(" WAIT COM .");//addedd
}
#endif
break;
default:
display.setCursor(26, 10);
display.println(" ? ? ? ");//addedd
break;
}
}
}