//固態Relay1、Relay2互切後,檢查IN與J1有無導通,多執行緒,可設定執行次數,1秒8下,6P
//2路固態繼電器模塊共陽極
#include "Button.h"
#include "EEPROM.h"
//------------繼電器腳-----------------
// Define Connections to 74HC595
const int latchPinA = 26; // ST_CP pin 12
const int clockPinA = 27; // SH_CP pin 11
const int dataPinA = 25; // DS pin 14
const byte LED_A[9] = { // 記錄0~9的七段數字
//GFEDCBA
B00000000,
B10000000,
B01000000,
B00100000,
B00010000,
B00001000,
B00000100,
B00000010,
B00000001
};
///-----------按鈕--------------------
Button button1(34); //設定選單
Button button2(39); //增加,預設,開始
Button button3(36); //減少,儲存
//------------導通檢查------------------
// Define Connections to 74HC165
const int dataPin = 17; /* Q7 */
const int clockPin = 16; /* CP */
const int latchPin = 15; /* PL */
// byte a[8];
byte incoming ;
//------EEPROM---------------
int address1 ; //EEPROM長度
uint32_t execution = 1000; //執行次數
uint32_t Timer2 = 250; //執行秒數
uint32_t valoare1 = 1000; //選單1用
uint32_t valoare2 = 250; //選單2用
bool judgment = true; //判斷是否異常
byte meniu = 0; //選單
char condition = '8'; //1執行有無導通
bool SendFlagA = false;
bool SendFlagB = false;
//------------lcd----------------------
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//-------------按鈕-------------------
//const int buttonPinA = 5; // 按鈕的引腳
#define buttonPinA 27 //按鈕1 GPIO 13
uint32_t buttonPushCounter0 = 0; // 開關訊號的改變次數,預設為 0
uint32_t buttonPushCounter1 = 0; // 開關訊號的改變次數,預設為 0
//------------控制秒數----------------------
uint32_t countA = 0; //計數器繼電器1
uint32_t countB = 0; //計數器繼電器2
//----------中斷服務--------
hw_timer_t *tim1 = NULL;
int tim1_IRQ_count = 0;
void tim1Interrupt()
{
// Serial.println("haha1");
tim1_IRQ_count++;
// Serial.println(timerAlarmEnabled(tim1));
}
//-----控製Relay---------------
void Relay(int comdataA) {
digitalWrite(latchPinA, LOW);
shiftOut(dataPinA, clockPinA, LSBFIRST, LED_A[comdataA]);// 先放個位數字HH
digitalWrite(latchPinA, HIGH);
}
void Relayonoff(char comdata) {
char message = comdata;
if (message == '1')
{
Relay(2); //開
delay(Timer2); //導通時間
Relay(0);//關
delay(10); //不導通時間
countA += 1;
}
else if (message == '2')
{
Relay(3); //開
delay(Timer2); //導通時間
Relay(0); //關
delay(10); //不導通時間
}
else if (message == '3')
{
Relay(4); //開
delay(Timer2); //導通時間
Relay(0); //關
delay(10); //不導通時間
}
else if (message == '4')
{
Relay(5); //開
delay(Timer2); //導通時間
Relay(0); //關
delay(10); //不導通時間
}
else if (message == '5')
{
Relay(6); //開
delay(Timer2); //導通時間
Relay(0); //關
delay(10); //不導通時間
}
else if (message == '6')
{
Relay(7); //開
delay(Timer2); //導通時間
Relay(0); //關
delay(10); //不導通時間
}
else if (message == '7')
{
Relay(8); //開
delay(Timer2); //導通時間
Relay(0); //關
delay(10); //不導通時間
countB += 1;
}
else if (message == '8')
{
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);
u8g2.print("導通開始");
u8g2.setCursor(62, 15);
u8g2.print(countA);
u8g2.setCursor(0, 30);
u8g2.print(incoming);
u8g2.setCursor(30, 30);
u8g2.print("成功");
u8g2.setCursor(62, 30);
u8g2.print(buttonPushCounter0);
u8g2.setCursor(0, 45);
u8g2.print("復歸開始");
u8g2.setCursor(62, 45);
u8g2.print(countB);
u8g2.setCursor(30, 60);
u8g2.print("成功");
u8g2.setCursor(62, 60);
u8g2.print(buttonPushCounter1);
u8g2.sendBuffer();//繪製緩衝區的內容
Serial.println("Error");
Serial.println(countA);
Serial.println(countB);
Serial.println(buttonPushCounter0);
Serial.println(buttonPushCounter1);
delay(1);
// execution = 1000; //設定運作次數歸零
countA = 0;
countB = 0;
buttonPushCounter0 = 0;
buttonPushCounter1 = 0;
delay(10);
Relay(8); //全部跳開
delay(10);
Relay(0); //關全部不通電
SendFlagA = false;
}
else
{
}
}
//-----------------導通檢查-------------------------
void turn_on() {
// // Step 1: Sample
// digitalWrite(latchPin, LOW);
// digitalWrite(latchPin, HIGH);
// // Step 2: Shift
// // Serial.print("Bits: ");
// for (byte i = 0; i < 8; i++) {
// // byte bit = digitalRead(dataPin);
// a[i] = digitalRead(dataPin);
// Serial.print(a[i]);
// digitalWrite(clockPin, HIGH); // Shift out the next bit
// digitalWrite(clockPin, LOW);
// }
// Serial.println("");
digitalWrite(latchPin, LOW);
digitalWrite(latchPin, HIGH);
incoming = shiftIn(dataPin, clockPin, MSBFIRST); //MSBFIRST //LSBFIRST
Serial.println(incoming);
}
void LEDmeniu() {
if (meniu == 0) {
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);
u8g2.print("開始! 請按+");
u8g2.setCursor(0, 30);
u8g2.print("次數:");
u8g2.setCursor(40, 30);
u8g2.print(execution);
u8g2.setCursor(0, 45);
u8g2.print("秒數:");
u8g2.setCursor(40, 45);
u8g2.print(Timer2);
u8g2.setCursor(70, 45);//設定繪製游標位置
u8g2.print("判斷:");//顯示內容
u8g2.setCursor(110, 45);
u8g2.print(judgment);
u8g2.setCursor(0, 60);
u8g2.print("M + - R");
u8g2.sendBuffer();//繪製緩衝區的內容
}
if (meniu == 1) {
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);
u8g2.print("目碌:");
u8g2.setCursor(40, 15);
u8g2.print(meniu);
u8g2.setCursor(0, 30);
u8g2.print("請修改!");
u8g2.setCursor(0, 45);
u8g2.print("次數:");
u8g2.setCursor(40, 45);
u8g2.print(execution);
u8g2.setCursor(0, 60);
u8g2.print("M + - R");
u8g2.sendBuffer();//繪製緩衝區的內容
}
if (meniu == 2) {
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);
u8g2.print("目碌:");
u8g2.setCursor(40, 15);
u8g2.print(meniu);
u8g2.setCursor(0, 30);
u8g2.print("請修改!");
u8g2.setCursor(0, 45);
u8g2.print("秒數:");
u8g2.setCursor(40, 45);
u8g2.print(Timer2);
u8g2.setCursor(0, 60);
u8g2.print("M + - R");
u8g2.sendBuffer();//繪製緩衝區的內容
}
if (meniu == 3) {
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);
u8g2.print("目碌:");
u8g2.setCursor(40, 15);
u8g2.print(meniu);
u8g2.setCursor(0, 30);
u8g2.print("是否判斷異常!");
u8g2.setCursor(0, 45);
u8g2.print("判斷異常:");
u8g2.setCursor(80, 45);
u8g2.print(judgment);
u8g2.setCursor(0, 60);
u8g2.print("M + - R");
u8g2.sendBuffer();//繪製緩衝區的內容
}
if (meniu == 4) {
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);
u8g2.print("目碌:");
u8g2.setCursor(40, 15);
u8g2.print(meniu);
u8g2.setCursor(0, 30);
u8g2.print("保存參數! ");
u8g2.setCursor(0, 45);
u8g2.print("+預設 -保存");
u8g2.setCursor(0, 60);
u8g2.print("M + - R");
u8g2.sendBuffer();//繪製緩衝區的內容
}
}
void setup() {
Serial.begin(115200);
//---------按鈕輸入--------
pinMode(buttonPinA, INPUT);//原來的 INPUT 改成 INPUT_PULLUP配置為輸入引腳並啟用內部上拉電阻
button1.begin();
button2.begin();
button3.begin();
//---------繼電器--------------------
// Define Connections to 74HC595
pinMode(latchPinA, OUTPUT);
pinMode(clockPinA, OUTPUT);
pinMode(dataPinA, OUTPUT);
Relay(0);//關
//------------導通檢查------------------
// Define Connections to 74HC165
pinMode(dataPin, INPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
digitalWrite(latchPin, HIGH);
//-----------lcd------------
u8g2.begin(); //初始化 U8G2 程式庫
u8g2.enableUTF8Print(); // 啟動 UTF8 支援
u8g2.setFont(u8g2_font_unifont_t_chinese1); //設置字體集
u8g2.setFontDirection(0); //設定顯示字串或字形的繪製方向。
//-----中斷服務--------------------
tim1 = timerBegin(1, 80, true);
timerAttachInterrupt(tim1, tim1Interrupt, true);
timerAlarmWrite(tim1, 1000000, true);
timerAlarmEnable(tim1);
//EEPROM 儲存execution、Timer2值
if (!EEPROM.begin(1000)) {}
address1 = 0;
Serial.println(EEPROM.readUInt(address1));
execution = EEPROM.readUInt(address1);
valoare1 = execution;
address1 += sizeof(address1);
Serial.println(EEPROM.readUInt(address1));
Timer2 = EEPROM.readUInt(address1);
valoare2 = Timer2;
address1 += sizeof(address1);
Serial.println(EEPROM.readUInt(address1));
judgment = EEPROM.readUInt(address1);
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);//設定繪製游標位置
u8g2.print("開始! 請按+");//顯示內容
u8g2.setCursor(0, 30);//設定繪製游標位置
u8g2.print("次數:");//顯示內容
u8g2.setCursor(40, 30);
u8g2.print(execution);
u8g2.setCursor(0, 45);//設定繪製游標位置
u8g2.print("秒數:");//顯示內容
u8g2.setCursor(40, 45);
u8g2.print(Timer2);
u8g2.setCursor(70, 45);//設定繪製游標位置
u8g2.print("判斷:");//顯示內容
u8g2.setCursor(110, 45);
u8g2.print(judgment);
u8g2.setCursor(0, 60);
u8g2.print("M + - R");
u8g2.sendBuffer();//繪製緩衝區的內容
}
void loop() {
if (button1.pressed()) { //設定選單
Serial.println("sw0 pushed");
meniu = meniu + 1;
if (meniu > 4) {
meniu = 0;
}
LEDmeniu();
}
if (button2.pressed()) { //增加
if (meniu == 0) { //開始運作
LEDmeniu();
Serial.print("開始運作");
Serial.println(condition);
condition = '1'; //開始運作
SendFlagA = true;
}
if (meniu == 1) { //次數增加
valoare1 += 1000;
execution = valoare1;
condition = '8'; //停止運作
LEDmeniu();
Serial.print("運作次數:");
Serial.println(execution);
}
if (meniu == 2) { //秒數增加
valoare2 += 10;
Timer2 = valoare2;
condition = '8'; //停止運作
LEDmeniu();
Serial.print("運作秒數:");
Serial.println(Timer2);
}
if (meniu == 3) { //判斷是否異常
judgment = true ;
condition = '8'; //停止運作
LEDmeniu();
Serial.print("判斷異常:");
Serial.println(judgment);
}
if (meniu == 4) { //預設秒數次數
// Write: Variables ---> EEPROM stores
address1 = 0;
execution = 1000;
Timer2 = 250;
judgment = true ;
EEPROM.writeUInt(address1, execution);
address1 += sizeof(execution);
EEPROM.writeUInt(address1, Timer2);
address1 += sizeof(Timer2);
EEPROM.writeUInt(address1, judgment);
EEPROM.commit(); //一次寫入
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);
u8g2.print("預設 OK!");
u8g2.setCursor(0, 30);//設定繪製游標位置
u8g2.print("次數:");//顯示內容
u8g2.setCursor(40, 30);
u8g2.print(execution);
u8g2.setCursor(0, 45);//設定繪製游標位置
u8g2.print("秒數:");//顯示內容
u8g2.setCursor(40, 45);
u8g2.print(Timer2);
u8g2.setCursor(70, 45);//設定繪製游標位置
u8g2.print("判斷:");//顯示內容
u8g2.setCursor(110, 45);
u8g2.print(judgment);
u8g2.sendBuffer();//繪製緩衝區的內容
}
}
if (button3.pressed()) { //減少
if (meniu == 1) {//次數減少
valoare1 -= 1000;
execution = valoare1;
condition = '8';
LEDmeniu();
Serial.print("運作次數:");
Serial.println(execution);
}
if (meniu == 2) { //秒數減少
valoare2 -= 10;
Timer2 = valoare2;
condition = '8';
LEDmeniu();
Serial.print("運作秒數:");
Serial.println(Timer2);
}
if (meniu == 3) { //判斷是否異常
judgment = false ;
condition = '8'; //停止運作
LEDmeniu();
Serial.print("判斷異常:");
Serial.println(judgment);
}
if (meniu == 4) { //儲存到EEPROM
// Write: Variables ---> EEPROM stores
address1 = 0;
EEPROM.writeUInt(address1, execution);
address1 += sizeof(execution);
EEPROM.writeUInt(address1, Timer2);
address1 += sizeof(Timer2);
EEPROM.writeUInt(address1, judgment);
EEPROM.commit(); //一次寫入
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);
u8g2.print("儲存 OK!");
u8g2.setCursor(0, 30);//設定繪製游標位置
u8g2.print("次數:");//顯示內容
u8g2.setCursor(40, 30);
u8g2.print(execution);
u8g2.setCursor(0, 45);//設定繪製游標位置
u8g2.print("秒數:");//顯示內容
u8g2.setCursor(40, 45);
u8g2.print(Timer2);
u8g2.setCursor(70, 45);//設定繪製游標位置
u8g2.print("判斷:");//顯示內容
u8g2.setCursor(110, 45);
u8g2.print(judgment);
u8g2.sendBuffer();//繪製緩衝區的內容
}
}
if ((SendFlagA) and ( execution != 0 )) {
if (condition == '1') {
Relayonoff('1'); //關閉Relayon2開啟Relayon1
turn_on();//檢查導通腳
if (((incoming == 62 ) and (judgment == true )) or (judgment == false )) { //按鈕有無按下255-1
buttonPushCounter0 ++; //按下次數
condition = '2'; //標記跳開程式
} else if (judgment == true ) {
Relayonoff('8'); //關閉Relayon1,2
condition = '8'; //標記跳開程式
}
}
if (condition == '2') {
Relayonoff('2'); //關閉Relayon2開啟Relayon1
turn_on();//檢查導通腳
if ((( incoming == 60 ) and (judgment == true )) or (judgment == false )) { //按鈕有無按下255-2
condition = '3'; //標記跳開程式
} else if (judgment == true ) {
Relayonoff('8'); //關閉Relayon1,2
condition = '8'; //標記跳開程式
}
}
if (condition == '3') {
Relayonoff('3'); //關閉Relayon2開啟Relayon1
turn_on();//檢查導通腳
if (((incoming == 56 ) and (judgment == true )) or (judgment == false )) { //按鈕有無按下255-4
condition = '4'; //標記跳開程式
} else if (judgment == true ) {
Relayonoff('8'); //關閉Relayon1,2
condition = '8'; //標記跳開程式
}
}
if (condition == '4') {
Relayonoff('4'); //關閉Relayon2開啟Relayon1
turn_on();//檢查導通腳
if ((( incoming == 48 ) and (judgment == true )) or (judgment == false )) { //按鈕有無按下255-8
condition = '5'; //標記跳開程式
} else if (judgment == true ) {
Relayonoff('8'); //關閉Relayon1,2
condition = '8'; //標記跳開程式
}
}
if (condition == '5') {
Relayonoff('5'); //關閉Relayon2開啟Relayon1
turn_on();//檢查導通腳
if ((( incoming == 32 ) and (judgment == true )) or (judgment == false )) { //按鈕有無按下255-16
condition = '6'; //標記跳開程式
} else if (judgment == true ) {
Relayonoff('8'); //關閉Relayon1,2
condition = '8'; //標記跳開程式
}
}
if (condition == '6') {
Relayonoff('6'); //關閉Relayon2開啟Relayon1
turn_on();//檢查導通腳
if ((( incoming == 0 ) and (judgment == true )) or (judgment == false )) { //按鈕有無按下255-32
condition = '7'; //標記跳開程式
} else if (judgment == true ) {
Relayonoff('8'); //關閉Relayon1,2
condition = '8'; //標記跳開程式
}
}
if (condition == '7') {
Relayonoff('7'); //關閉Relayon2開啟Relayon1
turn_on();//檢查導通腳
if ((( incoming == 63 ) and (judgment == true )) or (judgment == false )) { //按鈕有無按下255-64
buttonPushCounter1 ++; //放開次數
execution --;
condition = '1'; //標記跳開程式
} else if (judgment == true ) {
Relayonoff('8'); //關閉Relayon1,2
condition = '8'; //標記跳開程式
}
}
} else if ((SendFlagA) and ( execution == 0 )) {
Relayonoff('8'); //關閉Relayon1-8
condition = '8'; //標記跳開程式
SendFlagA = false;
// execution = EEPROM.readUInt(0);
Serial.println("運作結束");
}
if (tim1_IRQ_count >= 1) {
// timerAlarmEnable(tim1);
// Serial.println("count trigger");
tim1_IRQ_count = 0;
if (condition != '8') {
u8g2.clearBuffer();//清除記憶體中的所有緩衝區內的圖元
u8g2.setCursor(0, 15);
u8g2.print("導通開始");
u8g2.setCursor(62, 15);
u8g2.print(countA);
u8g2.setCursor(0, 30);
u8g2.print(incoming);
u8g2.setCursor(30, 30);
u8g2.print("成功");
u8g2.setCursor(62, 30);
u8g2.print(buttonPushCounter0);
u8g2.setCursor(0, 45);
u8g2.print("復歸開始");
u8g2.setCursor(62, 45);
u8g2.print(countB);
u8g2.setCursor(30, 60);
u8g2.print("成功");
u8g2.setCursor(62, 60);
u8g2.print(buttonPushCounter1);
u8g2.sendBuffer();//繪製緩衝區的內容
}
}
}