#include <stdio.h>
#include <string.h>
#include <stdarg.h>
// #include <MsTimer2.h>
#include <stdlib.h>
volatile bool state = true;
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ArduinoJson.h>
#include <PCF8574.h>
// 블루투스 통신을 위한 설정
// Set your Board and Server ID
#define BOARD_ID 2
#define MAX_CHANNEL 11 // for North America // 13 in Europe
#define LED_BUILTIN 2
uint8_t serverAddress[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
typedef struct struct_pairing { // new structure for pairing
uint8_t msgType;
uint8_t id;
uint8_t macAddr[6];
uint8_t channel;
} struct_pairing;
//Create 2 struct_message
struct_pairing pairingData;
enum PairingStatus {NOT_PAIRED, PAIR_REQUEST, PAIR_REQUESTED, PAIR_PAIRED,};
PairingStatus pairingStatus = NOT_PAIRED;
enum MessageType {PAIRING, DATA,};
MessageType messageType;
enum DataType {PAIR, SENSOR, VOLT, AMPERE, RELAY, CHECK, ANSWER_OK, };
DataType dataType;
#ifdef SAVE_CHANNEL
int lastChannel;
#endif
int channel = 1;
unsigned long currentMillis = millis();
unsigned long previousMillis = 0; // Stores last time temperature was published
const long interval = 10000; // Interval at which to publish sensor readings
unsigned long start; // used to measure Pairing time
unsigned int readingId = 0;
// 블루투스 통신을 위한 설정 끝
#define CHK_ON 5.00
#define CHK_OFF 3.00
#define GUARD_ON 26 // 경계진입(문잠김)
#define GUARD_OFF 27 // 경계해제(문열림)
#define PIN_BTN_SLEEP 16 // Sleep/NotSleep 선택
#define PIN_BTN_BLUETOOTH 13 // 블루통신 선택 (On:실제보드 / Off:시물레이션)
// 각 센서가 ESP32에 연결되어 있는 핀번호 정의
#define PIN_SENSOR_TYPE 0 // 센서체크방식 키박스/퓨즈박스 선택
#define PIN_SENSOR_CIGAR 32
#define PIN_SENSOR_CLOCK 35
#define PIN_SENSOR_IG 26
#define PIN_SENSOR_WIPER 25
#define PIN_SENSOR_AIRBAG 33
#define PIN_SENSOR_START 34
// #define PIN_SENSOR_DOORLOCK 34
#define PIN_SENSOR_KEY_IN 27 // ESP32 P27
#define PIN_SENSOR_KEY_ACC 32
#define PIN_SENSOR_KEY_ON 35
#define PIN_SENSOR_KEY_IG1 26
#define PIN_SENSOR_KEY_IG2 25
#define PIN_SENSOR_KEY_START 34
// #define PIN_SENSOR_KEY_OUT 25
// 배터리 전압계, 전류계, 릴레이 연결체크 센서들이 멀티플렉서 각각의 핀에 연결된 핀(채널)번호
#define PIN_VOLT_MAIN 0 // MUX I0
#define PIN_VOLT_SUB 1
#define PIN_VOLT_SUPERCAP1 2
#define PIN_VOLT_SUPERCAP2 3
#define PIN_VOLT_BOOSTER 4
#define PIN_AMP_SELF 5
#define PIN_AMP_MAIN 6
#define PIN_AMP_SUB 7
#define PIN_AMP_SUPERCAP 8
#define PIN_AMP_JUMPSTARTER 9
#define PIN_SENSOR_CON_MAIN 12
#define PIN_SENSOR_CON_SUB 13
#define PIN_SENSOR_CON_SUPERCAP 10
#define PIN_SENSOR_CON_OTHER 11
// 릴레이 전원 연결 핀번호
#define RELAY_CON_GND 17 // ESP32에 집적 연결
// 릴레이가 PCF8574에 연결된 핀(채널)번호
#define RELAY_CON_MAIN 0 // PCF8574 #1 P0
#define RELAY_CON_SUB 1
#define RELAY_CON_SUPERCAP 2
#define RELAY_CON_JUMPSTARTER 3
#define RELAY_RACH_MAIN_ON 4
#define RELAY_RACH_MAIN_OFF 5
#define RELAY_CON_CHARGER 6
#define RELAY_CON_BOOSTER_SELECT 0 // PCF8574 #2 P0
#define RELAY_CON_BOOSTER_INPUT 1
#define RELAY_CON_BOOSTER_OUTPUT 2
// 키 상태 정의
// #define STATE_KEY_OUT 0 // 키 삽입 안됨
// #define STATE_KEY_IN 1 // 키 삽입
// #define STATE_KEY_ACC 2 // 키 ACC
// #define STATE_KEY_ON 3 // 키 ON
// #define STATE_KEY_START 4 // 키 Start
enum KeyState {
STATE_KEY_OUT, // 키 삽입 안됨
STATE_KEY_IN, // 키 삽입
STATE_KEY_ACC, // 키 ACC
STATE_KEY_ON, // 키 ON
STATE_KEY_START, // 키 Start
};
KeyState keyState = STATE_KEY_OUT;
enum BoosterInputSelect {
MAIN, // 주배터리
SUB, // 보조배터리
};
#define STATE_UNLOCK 0 // 경계해제
#define STATE_LOCK 100 // 경계
#define OFF 0 // 시동끔
#define ON 10 // 시동걸림
// #define ON true
// #define OFF false
// 작업프로세스 정의
#define WORK_NONE 0
#define WORK_MAIN_BAT_CONNECT 1
#define WORK_MAIN_BAT_DISCONNECT 2
#define WORK_SUB_BAT_CONNECT 3
#define WORK_SUB_BAT_DISCONNECT 4
#define WORK_SUPERCAP_CONNECT 5
#define WORK_SUPERCAP_DISCONNECT 6
#define WORK_JUMPSTARTER_CONNECT 7
#define WORK_JUMPSTARTER_DISCONNECT 8
#define WORK_CHARGER_CONNECT 9
#define WORK_CHARGER_DISCONNECT 10
#define WORK_BOOSTER_CONNECT 11
#define WORK_BOOSTER_DISCONNECT 12
#define WORK_SLEEP_NOW 99
bool state_changed = false;
bool sleep_reserved = false;
// Floats for ADC voltage & Input voltage
float adc_voltage = 0.0;
float in_voltage = 0.0;
// Floats for resistor values in divider (in ohms)
float R1 = 30000.0;
float R2 = 7500.0;
// Float for Reference Voltage
float ref_voltage = 5.0;
// Integer for ADC value
int adc_value = 0;
typedef struct {
uint8_t msgType;
uint8_t id;
float temp;
float hum;
unsigned int readingId;
} struct_msg_TempHum;
typedef struct {
float input;
float output;
} boosterVolt_value;
typedef struct {
short input;
short output;
} short_boosterVolt_value;
typedef struct {
float main;
float sub;
boosterVolt_value booster;
float supercap1;
float supercap2;
} batVolt_value;
typedef struct {
short main;
short sub;
short_boosterVolt_value booster;
short supercap1;
short supercap2;
} short_batVolt_value;
typedef struct {
float self;
float main;
float sub;
float booster;
float supercap;
float jumpstarter;
} ampere_value;
typedef struct {
short self;
short main;
short sub;
short booster;
short supercap;
short jumpstarter;
} short_ampere_value;
typedef struct {
float keyin;
float cigarjack;
float clock;
float ignition;
float wiper;
float airbag;
float start;
} sensorVolt_value;
typedef struct {
short keyin;
short cigarjack;
short clock;
short ignition;
short wiper;
short airbag;
short start;
} short_sensorVolt_value;
typedef struct {
bool keyin;
bool cigarjack;
bool clock;
bool ignition;
bool wiper;
bool airbag;
bool start;
} sensor_value;
typedef struct {
BoosterInputSelect select = MAIN;
bool input;
bool output;
} booster_value;
typedef struct {
bool main;
bool sub;
bool supercap;
bool jumpstarter;
bool latching;
bool charger;
booster_value booster;
} relay_value;
typedef struct {
bool main;
bool sub;
bool supercap;
bool jumpstarter;
bool latching;
bool charger;
booster_value booster;
} relay_state_value;
// 블루투스통신 자료 구조 선언
typedef struct {
uint8_t msgType; // 메세지 타입
uint8_t dataType; // 데이터 타입
uint8_t bid; // Board ID
unsigned int sid; // 일련번호
short_batVolt_value data; // 볼트
} struct_msg_short_Voltage;
typedef struct {
uint8_t msgType; // 메세지 타입
uint8_t dataType; // 데이터 타입
uint8_t bid; // Board ID
unsigned int sid; // 일련번호
short_ampere_value data; // 암페어
} struct_msg_short_Ampere;
typedef struct {
uint8_t msgType; // 메세지 타입
uint8_t dataType; // 데이터 타입
uint8_t bid; // Board ID
unsigned int sid; // 일련번호
short_sensorVolt_value data; // 센서볼트
} struct_msg_short_SensorVolt;
typedef struct {
uint8_t msgType; // 메세지 타입
uint8_t dataType; // 데이터 타입
uint8_t bid; // Board ID
unsigned int sid; // 일련번호
sensor_value data; // 센서 H/L
} struct_msg_Sensor;
typedef struct {
uint8_t msgType; // 메세지 타입
uint8_t dataType; // 데이터 타입
uint8_t bid; // Board ID
unsigned int sid; // 일련번호
relay_value data; // 릴레이 H/L
} struct_msg_Relay;
typedef struct {
uint8_t msgType; // 메세지 타입
uint8_t dataType; // 데이터 타입
uint8_t bid; // Board ID
unsigned int sid; // 일련번호
relay_state_value data; // 릴레이 체크 H/L
} struct_msg_RelayState;
batVolt_value batVolt = { 0.00, };
ampere_value ampere = { 0.00, };
sensorVolt_value sensorVolt = { 0.00, };
// short_batVolt_value short_batVolt = { 0, };
// short_ampere_value short_ampere = { 0, };
// short_sensorVolt_value short_sensorVolt = { 0, };
sensor_value sensor = { LOW, };
relay_value relay = { false, };
relay_state_value relayState = { false, };
struct_msg_short_Voltage msg_batVolt;
struct_msg_short_Ampere msg_Ampere;
struct_msg_short_SensorVolt msg_SensorVolt;
struct_msg_Sensor msg_Sensor;
struct_msg_Relay msg_Relay;
struct_msg_RelayState msg_RelayState;
struct_msg_short_Voltage old_msg_batVolt;
struct_msg_short_Ampere old_msg_Ampere;
struct_msg_short_SensorVolt old_msg_SensorVolt;
struct_msg_Sensor old_msg_Sensor;
struct_msg_Relay old_msg_Relay;
struct_msg_RelayState old_msg_RelayState;
// int keyState = STATE_KEY_OUT;
int engine_state = OFF;
int old_keyState = STATE_KEY_OUT;
// int old_keyState = keyState;
int old_engine_state = OFF;
int sensors_logic = 0;
int old_sensors_logic = 65535;
byte sensors_bit = 0b00000000;
byte old_sensors_bit = 0b11111111;
unsigned long past_volt = 0;
unsigned long past_key = 0;
unsigned long past_nextwork = 0;
unsigned long past_sleep = 0;
unsigned long past_go_sleep = 0;
int flag_volt = 0;
int flag_key = 0;
int flag_nextwork = 0;
int flag_sleep = 0;
int flag_go_sleep = 0;
int time_delay_volt = 0;
int time_delay_key = 0;
int time_delay_nextwork = 0;
// int time_delay_sleep_check = 1000;
int time_delay_go_sleep = 5000;
// Set I2C address
// int address = 0x20;
int next_func_name = WORK_NONE; // WORK_SUB_BAT_CONNECT;
int nextjob[10][2] = { 0, };
char state_buf1[12] = {"",};
char state_buf2[12] = {"",};
// // CD74HC4067 핀정의
#define MUX1 0
#define MUX2 1
#define S0 0 // 채널 bit
#define S1 1 // 채널 bit
#define S2 2 // 채널 bit
#define S3 3 // 채널 bit
#define E 4 // 채널설정 Start/End
#define COM 5 // 시그널
#define MUX1_S0 26 // 채널 bit
#define MUX1_S1 25 // 채널 bit
#define MUX1_S2 33 // 채널 bit
#define MUX1_S3 32 // 채널 bit
#define MUX1_E 14 // 채널설정 Start/End
#define MUX1_COM 34 // 시그널
#define MUX2_S0 19 // 채널 bit
#define MUX2_S1 18 // 채널 bit
#define MUX2_S2 17 // 채널 bit
#define MUX2_S3 16 // 채널 bit
#define MUX2_E 23 // 채널설정 Start/End
#define MUX2_COM 4 // 시그널
const uint8_t Mux_Pins[1][6] = {
{ MUX1_S0, MUX1_S1, MUX1_S2, MUX1_S3, MUX1_E, MUX1_COM },
// { MUX2_S0, MUX2_S1, MUX2_S2, MUX2_S3, MUX2_E, MUX2_COM },
};
#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex
#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP 5 /* Time ESP32 will go to sleep (in seconds) */
RTC_DATA_ATTR int bootCount = 0;
// hw_timer_t *Timer0_Cfg = NULL;
/*
==========================================================================================
기존 정의 완료
모듈별 장치 정의
==========================================================================================
*/
PCF8574 PCF_01(0x20);
PCF8574 PCF_02(0x21);
#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 resetpin)
Adafruit_SSD1306 oled1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Adafruit_SSD1306 oled2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Adafruit_SSD1306 oled3(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define MODULE_NAME "Relay Modulr"
#define MODULE_NO1 "#1"
#define MODULE_NO2 "#2"
#define MODULE_NO3 "#3"
#define MODULE_NO4 "#4"
/*
==========================================================================================
정의 완료
프로그램 시작
==========================================================================================
*/
void job_add(int job_name, int delay_time) {
for(int i=0; i<=10; i++) {
if (nextjob[i][0] == 0) {
nextjob[i][0] = job_name;
nextjob[i][1] = delay_time;
break;
}
}
}
void job_pull() {
for(int i=0; i<10; i++) {
nextjob[i][0] = nextjob[i+1][0];
nextjob[i][1] = nextjob[i+1][1];
if (nextjob[i+1][0] == 0) {
break;
}
}
}
void job_clear() {
for(int i=0; i<10; i++) {
nextjob[i][0] = WORK_NONE;
nextjob[i][1] = 0;
}
sleep_reserved = false;
}
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
}
}
void mux_pin_init(int iMux) {
for (int i=0; i<4; i++) {
// Serial.println(Mux_Pins[iMux][i]);
pinMode(Mux_Pins[iMux][i], OUTPUT);
}
}
void variable_init() {
// batVolt.main = 0.00;
// batVolt.sub = 0.00;
// batVolt.booster = 0.00;
// batVolt.supercap1 = 0.00;
// batVolt.supercap2 = 0.00;
// ampere.main = 0.00;
// ampere.sub = 0.00;
// ampere.supercap = 0.00;
// ampere.jumpstarter = 0.00;
// ampere.self = 0.00;
// sensorVolt.keyin = 0.00;
// sensorVolt.cigarjack = 0.00;
// sensorVolt.clock = 0.00;
// sensorVolt.ignition = 0.00;
// sensorVolt.wiper = 0.00;
// sensorVolt.airbag = 0.00;
// sensorVolt.start = 0.00;
// sensor.keyin = LOW;
// sensor.cigarjack = LOW;
// sensor.clock = LOW;
// sensor.ignition = LOW;
// sensor.wiper = LOW;
// sensor.airbag = LOW;
// sensor.start = LOW;
// relay.main = false;
// relay.sub = false;
// relay.supercap = false;
// relay.jumpstarter = false;
// relay.latching = false;
// relay.charger = false;
// relay.booster = false;
msg_batVolt.sid = 0;
msg_Sensor.sid = 0;
msg_SensorVolt.sid = 0;
msg_Ampere.sid = 0;
msg_Relay.sid = 0;
msg_RelayState.sid = 0;
old_msg_batVolt.sid = 0;
old_msg_Sensor.sid = 0;
old_msg_SensorVolt.sid = 0;
old_msg_Ampere.sid = 0;
old_msg_Relay.sid = 0;
old_msg_RelayState.sid = 0;
}
void display_start(Adafruit_SSD1306 &oled, char* module_name, char* module_no) {
Serial.print(module_name);
Serial.print(" ");
Serial.println(module_no);
// Clear the buffer.
oled.clearDisplay();
// Display Text
oled.setTextColor(WHITE);
oled.drawRect(0, 0, 127, 63, WHITE);
oled.setTextSize(1);
oled.setCursor(20, 16);
oled.println(module_name);
oled.setTextSize(2);
oled.setCursor(50, 30);
oled.println(module_no);
oled.display();
}
float read_volt(int PINNO) {
// int adc_value = analogRead(PINNO);
adc_value = analogRead(PINNO);
// Determine voltage at ADC input
// adc_voltage = (adc_value * ref_voltage) / 1024.0;
adc_voltage = (adc_value * ref_voltage) / 4098.0;
// Calculate voltage at divider input
in_voltage = adc_voltage / (R2/(R1+R2)) ;
// Print results to Serial Monitor to 2 decimal places
// Serial.print("Input Voltage = ");
// Serial.println(in_voltage, 2);
return in_voltage;
}
void disp_volt_sub(char* str_title, float volt, Adafruit_SSD1306 &oled) {
char buf[80];
sprintf(buf, "%s%5.2f", str_title, volt);
oled.println(buf);
}
void print_volt(char* str_title, float volt) {
Serial.print(str_title);
Serial.print(" : ");
Serial.print(volt, 2);
Serial.println("V");
}
// void exem_sprintf()
// {
// sprintf(buf, "문자들: '%c', '%c'", 'a', (char)97); Serial.println(buf);
// sprintf(buf, "숫자들: %10i, %li", 254, 254); Serial.println(buf);
// sprintf(buf, "숫자들: %d, %ld", 254, 254); Serial.println(buf);
// sprintf(buf, "숫자들: %d, %ld", (unsigned int)(v_main + 1), (unsigned long)(value + 1)); Serial.println(buf);
// sprintf(buf, "숫자들: %u, %lu", (unsigned int)(v_main + 1), (unsigned long)(value + 1)); Serial.println(buf);
// sprintf(buf, "' ' 문자를 앞에 넣은 숫자: %10d", v_main); Serial.println(buf);
// sprintf(buf, "'0' 문자를 앞에 넣은 숫자: %010d", v_main); Serial.println(buf);
// sprintf(buf, "왼쪽 정렬: %-10d %ld", v_main, value); Serial.println(buf);
// sprintf(buf, "오른쪽 정렬: %10d %ld", v_main, value); Serial.println(buf);
// sprintf(buf, "오른쪽 정렬: %10.8d %ld", v_main, value); Serial.println(buf);
// sprintf(buf, "+ 기호: %+10d %+ld", v_main, value); Serial.println(buf);
// sprintf(buf, "진수들: %04d %04o %#4o %04x %#4x %04X %#4X", 254, 254, 254, 254, 254, 254, 254); Serial.println(buf);
// sprintf(buf, "진수들: %4d %4o %#4o %4x %#4x %4X %#4X", 254, 254, 254, 254, 254, 254, 254); Serial.println(buf);
// sprintf(buf, "포인터: %p", &buf); Serial.println(buf);
// sprintf(buf, "문자열: %s", "아두이노"); Serial.println(buf);
// sprintf(buf, "Main : %4d, %2.2d Volt", value, v_main);
// Serial.println(buf);
// }
// -- END OF FILE --
void setChannelMux(int iMux, uint8_t channel) {
digitalWrite(Mux_Pins[iMux][E], HIGH); // Disable chip before changing channel.
delay(1);
for(int8_t i = 3; i >= 0; i--) {
int8_t b = (channel >> i) & 1;
digitalWrite(Mux_Pins[iMux][i], b);
// Serial.print(b);
}
digitalWrite(Mux_Pins[iMux][E], LOW); // Enable chip after changing channel.
delay(1);
// Serial.print(": ");
}
// void setChannelMux(int iMux, byte channel) {
// digitalWrite(Mux_Pins[iMux][E], HIGH); // Disable chip before changing channel.
// digitalWrite(Mux_Pins[iMux][3], bitRead(channel, 0));
// digitalWrite(Mux_Pins[iMux][2], bitRead(channel, 1));
// digitalWrite(Mux_Pins[iMux][1], bitRead(channel, 2));
// digitalWrite(Mux_Pins[iMux][0], bitRead(channel, 3));
// digitalWrite(Mux_Pins[iMux][E], LOW); // Enable chip after changing channel.
// delay(1);
// }
int readMux(int iMux, uint8_t channel) {
// pinMode(Mux_Pins[iMux][COM], INPUT);
setChannelMux(iMux, channel);
return analogRead(Mux_Pins[iMux][COM]);
}
// int readMux(int iMux, byte channel){
// digitalWrite(Mux_Pins[iMux][E], HIGH); // Disable chip before changing channel.
// digitalWrite(Mux_Pins[iMux][0], bitRead(channel, 0));
// digitalWrite(Mux_Pins[iMux][1], bitRead(channel, 1));
// digitalWrite(Mux_Pins[iMux][2], bitRead(channel, 2));
// digitalWrite(Mux_Pins[iMux][3], bitRead(channel, 3));
// digitalWrite(Mux_Pins[iMux][E], LOW); // Enable chip after changing channel.
// return analogRead(Mux_Pins[iMux][COM]);
// }
void digitalWriteMux(int iMux, uint8_t channel, bool bData) {
// pinMode(Mux_Pins[iMux][COM], OUTPUT);
setChannelMux(iMux, channel);
digitalWrite(Mux_Pins[iMux][COM], bData);
}
float mux_read_volt(int iMux, uint8_t channel) {
// adc_value = analogRead(PINNO);
adc_value = readMux(iMux, channel);
// Determine voltage at ADC input
// adc_voltage = (adc_value * ref_voltage) / 1024.0;
adc_voltage = (adc_value * ref_voltage) / 4098.0;
// Calculate voltage at divider input
in_voltage = adc_voltage / (R2/(R1+R2)) ;
// Print results to Serial Monitor to 2 decimal places
// Serial.print("Input Voltage = ");
// Serial.println(in_voltage, 2);
return in_voltage;
}
void func_read_battery_volt() {
batVolt.main = mux_read_volt(MUX1, PIN_VOLT_MAIN);
// batVolt.main = read_volt(PIN_VOLT_MAIN);
batVolt.sub = mux_read_volt(MUX1, PIN_VOLT_SUB);
batVolt.booster.output = mux_read_volt(MUX1, PIN_VOLT_BOOSTER);
batVolt.supercap1 = mux_read_volt(MUX1, PIN_VOLT_SUPERCAP1);
batVolt.supercap2 = mux_read_volt(MUX1, PIN_VOLT_SUPERCAP2);
if (relay.booster.select == MAIN) {
batVolt.booster.input = batVolt.main;
}
else {
batVolt.booster.input = batVolt.sub;
}
}
void func_read_circuit_current() {
ampere.main = mux_read_volt(MUX1, PIN_AMP_MAIN);
// batVolt.main = read_volt(PIN_VOLT_MAIN);
ampere.sub = mux_read_volt(MUX1, PIN_AMP_SUB);
ampere.jumpstarter = mux_read_volt(MUX1, PIN_AMP_JUMPSTARTER);
ampere.supercap = mux_read_volt(MUX1, PIN_AMP_SUPERCAP);
ampere.self = mux_read_volt(MUX1, PIN_AMP_SELF);
}
void func_read_fusebox_sensor() {
sensorVolt.keyin = read_volt(PIN_SENSOR_KEY_IN);
// sensorVolt.cigarjack = mux_read_volt(MUX1, PIN_SENSOR_CIGAR);
// // sensorVolt.cigarjack = digitalRead(PIN_SENSOR_CIGAR);
// // sensorVolt.cigarjack = read_volt(PIN_SENSOR_CIGAR);
// sensorVolt.clock = mux_read_volt(MUX1, PIN_SENSOR_CLOCK);
// sensorVolt.ignition = mux_read_volt(MUX1, PIN_SENSOR_IG);
// sensorVolt.wiper = mux_read_volt(MUX1, PIN_SENSOR_WIPER);
// sensorVolt.airbag = mux_read_volt(MUX1, PIN_SENSOR_AIRBAG);
// sensorVolt.start = mux_read_volt(MUX1, PIN_SENSOR_START);
sensorVolt.cigarjack = read_volt(PIN_SENSOR_CIGAR);
sensorVolt.clock = read_volt(PIN_SENSOR_CLOCK);
sensorVolt.ignition = read_volt(PIN_SENSOR_IG);
sensorVolt.wiper = read_volt(PIN_SENSOR_WIPER);
sensorVolt.airbag = read_volt(PIN_SENSOR_AIRBAG);
sensorVolt.start = read_volt(PIN_SENSOR_START);
sensor.keyin = (sensorVolt.keyin > CHK_ON) ? HIGH : LOW;
sensor.cigarjack = (sensorVolt.cigarjack > CHK_ON) ? HIGH : LOW;
sensor.clock = (sensorVolt.clock > CHK_ON) ? HIGH : LOW;
sensor.ignition = (sensorVolt.ignition > CHK_ON) ? HIGH : LOW;
sensor.wiper = (sensorVolt.wiper > CHK_ON) ? HIGH : LOW;
sensor.airbag = (sensorVolt.airbag > CHK_ON) ? HIGH : LOW;
sensor.start = (sensorVolt.start > CHK_ON) ? HIGH : LOW;
}
void func_display_volt(Adafruit_SSD1306 &oled) {
func_read_battery_volt();
oled.clearDisplay();
if (sleep_reserved == true) {
oled.drawRect(0, 0, 127, 63, WHITE);
}
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(3, 3);
oled.println("Battery");
oled.println(" Check");
oled.setTextColor(WHITE);
oled.setTextSize(2);
oled.setCursor(66, 3);
disp_volt_sub("", batVolt.booster.output, oled);
oled.setCursor(3, 25);
disp_volt_sub("", batVolt.main, oled);
oled.setCursor(66, 25);
disp_volt_sub("", batVolt.sub, oled);
oled.setCursor(3, 45);
disp_volt_sub("", batVolt.supercap1, oled);
oled.setCursor(66, 45);
disp_volt_sub("", batVolt.supercap2, oled);
oled.display();
}
void func_display_current(Adafruit_SSD1306 &oled) {
func_read_circuit_current();
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(3, 3);
oled.println("Current");
oled.println(" Check");
oled.setTextColor(WHITE);
oled.setTextSize(2);
oled.setCursor(66, 3);
disp_volt_sub("", ampere.self, oled);
oled.setCursor(3, 25);
disp_volt_sub("", ampere.main, oled);
oled.setCursor(66, 25);
disp_volt_sub("", ampere.sub, oled);
oled.setCursor(3, 45);
disp_volt_sub("", ampere.supercap, oled);
oled.setCursor(66, 45);
disp_volt_sub("", ampere.jumpstarter, oled);
oled.display();
}
void func_read_relayState_check_sensor() {
int temp_volt = 0;
temp_volt = mux_read_volt(MUX1, PIN_SENSOR_CON_MAIN);
relayState.main = (temp_volt > CHK_ON) ? true : false;
temp_volt = mux_read_volt(MUX1, PIN_SENSOR_CON_SUB);
relayState.sub = (temp_volt > CHK_ON) ? true : false;
temp_volt = mux_read_volt(MUX1, PIN_SENSOR_CON_SUPERCAP);
relayState.supercap = (temp_volt > CHK_ON) ? true : false;
}
// void disp_relay_state(Adafruit_SSD1306 &oled) {
// if (relay.main) oled.fillCircle(6, 6, 6, WHITE);
// else oled.drawCircle(6, 6, 6, WHITE);
// if (relay.sub) oled.fillCircle(22, 6, 6, WHITE);
// else oled.drawCircle(22, 6, 6, WHITE);
// if (relay.supercap) oled.fillCircle(38, 6, 6, WHITE);
// else oled.drawCircle(38, 6, 6, WHITE);
// if (relay.jumpstart) oled.fillCircle(54, 6, 6, WHITE);
// else oled.drawCircle(54, 6, 6, WHITE);
// if (relay.latching) oled.fillCircle(70, 6, 6, WHITE);
// else oled.drawCircle(70, 6, 6, WHITE);
// if (relay.charger) oled.fillCircle(86, 6, 6, WHITE);
// else oled.drawCircle(86, 6, 6, WHITE);
// if (relay.booster.input) oled.fillCircle(102, 6, 6, WHITE);
// else oled.drawCircle(102, 6, 6, WHITE);
// }
// void disp_relay_state_check(Adafruit_SSD1306 &oled) {
// if (relayState.main) oled.fillCircle(117, 22, 6, WHITE);
// else oled.drawCircle(117, 22, 6, WHITE);
// if (relayState.sub) oled.fillCircle(117, 38, 6, WHITE);
// else oled.drawCircle(117, 38, 6, WHITE);
// if (relayState.supercap) oled.fillCircle(117, 54, 6, WHITE);
// else oled.drawCircle(117, 54, 6, WHITE);
// }
void disp_keyState(Adafruit_SSD1306 &oled, char* strState1="", char* strState2="") {
char buf1[80];
char buf2[80];
if (strState1 == "") {
sprintf(buf1, "%s", state_buf1);
sprintf(buf2, "%s", state_buf2);
}
else {
sprintf(buf1, "%s", strState1);
sprintf(buf2, "%s", strState2);
sprintf(state_buf1, "%s", buf1);
sprintf(state_buf2, "%s", buf2);
}
oled.clearDisplay();
// disp_relay_state(oled);
// disp_relay_state_check(oled);
oled.setTextSize(2);
oled.setTextColor(WHITE);
oled.setCursor(5, 25);
oled.println(buf1);
oled.setCursor(5, 45);
oled.println(buf2);
// oled.setCursor(0, 55);
// // disp_volt_sub("START", sensorVolt.ignition, oled);
// disp_volt_sub("IG1:", sensorVolt.ignition, oled);
oled.display();
}
void disp_sleep_reserved(Adafruit_SSD1306 &oled) {
// if (sleep_reserved == true) {
oled.drawRect(0, 0, 127, 63, (sleep_reserved == true) ? WHITE : BLACK);
// }
// else {
// }
oled.display();
}
void func_check_state_logical() {
func_read_fusebox_sensor();
int this_sensors_logic = 0;
byte this_sensors_bit = 0b00000000;
int n_keyin = 0;
if (sensor.keyin == HIGH) {
n_keyin = 1;
bitWrite(this_sensors_bit, 0, 1);
}
int n_cigarjack = 0;
if (sensor.cigarjack == HIGH) {
n_cigarjack = 2;
bitWrite(this_sensors_bit, 1, 1);
}
int n_clock = 0;
if (sensor.clock == HIGH) {
n_clock = 4;
bitWrite(this_sensors_bit, 2, 1);
}
int n_ignition = 0;
if (sensor.ignition == HIGH) {
n_ignition = 8;
bitWrite(this_sensors_bit, 3, 1);
}
int n_wiper = 0;
if (sensor.wiper == HIGH) {
n_wiper = 16;
bitWrite(this_sensors_bit, 4, 1);
}
int n_airbag = 0;
if (sensor.airbag == HIGH) {
n_airbag = 32;
bitWrite(this_sensors_bit, 5, 1);
}
int n_start = 0;
if (sensor.start == HIGH) {
n_start = 64;
bitWrite(this_sensors_bit, 6, 1);
}
this_sensors_logic = n_start + n_airbag + n_wiper + n_ignition + n_clock + n_cigarjack + n_keyin;
// 000 0000 // Key Out
char buf[80];
// switch(this_sensors_logic) {
// case 0: // 000 0000 // Key Out
// case 1: // 000 0001 // Key In
// case 3: // 000 0011 // Key ACC, 시동준비
// case 63: // 011 1111 // Key ON, 시동준비
// case 109: // 110 1101 // Key Start
// case 55: // 011 0111 // Key ON, 시동걸림
// case 35: // 010 0011 // Key ACC, 시동끔
// sensors_logic = this_sensors_logic;
// }
switch(this_sensors_bit) {
case 0b00000000: // 000 0000 // Key Out
case 0b00000001: // 000 0001 // Key In
case 0b00000011: // 000 0011 // Key ACC, 시동준비
case 0b00111111: // 011 1111 // Key ON, 시동준비
case 0b01101101: // 110 1101 // Key Start
case 0b00110111: // 011 0111 // Key ON, 시동걸림
case 0b00100011: // 010 0011 // Key ACC, 시동끔
// sensors_logic = this_sensors_logic;
sensors_bit = this_sensors_bit;
}
// sprintf(buf, "%5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %d %d %d %d %d %d",
// sensorVolt.keyin, sensorVolt.cigarjack, sensorVolt.clock, sensorVolt.ignition, sensorVolt.wiper, sensorVolt.airbag, sensorVolt.start,
// this_sensors_logic, sensors_logic, old_sensors_logic, this_sensors_bit, sensors_bit, old_sensors_bit);
// Serial.println(buf);
// if (old_sensors_logic != sensors_logic) {
if (old_sensors_bit != sensors_bit) {
old_keyState = keyState;
old_engine_state = engine_state;
job_clear();
// l_keyin = HIGH;
// switch(sensors_logic) {
switch(sensors_bit) {
// case 0: // 0000000 // Key Out
case 0b00000000: // 0000000 // Key Out
keyState = STATE_KEY_OUT;
// l_keyin = LOW;
engine_state = OFF;
sprintf(buf, "센서 old:%3d New:%3d %s", old_sensors_logic, sensors_logic, "상태 : KEY OUT, 경계, 엔진OFF");
Serial.println(buf);
break;
// case 1: // 0000001 // Key In
case 0b00000001: // 0000001 // Key In
keyState = STATE_KEY_IN;
engine_state = OFF;
sprintf(buf, "센서 old:%3d New:%3d %s", old_sensors_logic, sensors_logic, "상태 : KEY IN, 엔진OFF");
Serial.println(buf);
break;
// case 3: // 0000011 // Key ACC, 시동준비
case 0b00000011: // 0000011 // Key ACC, 시동준비
keyState = STATE_KEY_ACC;
engine_state = OFF;
sprintf(buf, "센서 old:%3d New:%3d %s", old_sensors_logic, sensors_logic, "상태 : KEY ACC, 시동준비");
Serial.println(buf);
break;
// case 63: // 0111111 // Key ON, 시동준비
case 0b00111111: // 0111111 // Key ON, 시동준비
keyState = STATE_KEY_ON;
engine_state = OFF;
Serial.println("상태 : KEY ON, 시동준비");
break;
// case 109: // 1101101 // Key Start
case 0b01101101: // 1101101 // Key Start
keyState = STATE_KEY_START;
engine_state = OFF;
Serial.println("상태 : KEY START, 시동");
break;
// case 55: // 0110111 // Key ON, 시동걸림
case 0b00110111: // 0110111 // Key ON, 시동걸림
keyState = STATE_KEY_ON;
engine_state = ON;
Serial.println("상태 : KEY ON, 시동걸림");
break;
// case 35: // 0100011 // Key ACC, 시동끔
case 0b00100011: // 0100011 // Key ACC, 시동끔
keyState = STATE_KEY_ACC;
engine_state = OFF;
Serial.println("상태 : KEY ACC, 시동꺼짐");
break;
}
}
}
void func_set_netxjob(Adafruit_SSD1306 &oled) {
switch(keyState) {
case STATE_KEY_OUT:
disp_keyState(oled, "KEY OUT", "OFF");
// 슬립모드가 필요함
// job_add(WORK_BOOSTER_DISCONNECT, 0);
// job_add(WORK_SUB_BAT_CONNECT, 0);
// job_add(WORK_SUPERCAP_DISCONNECT, 0);
// job_add(WORK_CHARGER_DISCONNECT, 0);
// job_add(WORK_JUMPSTART_DISCONNECT, 0);
// job_add(WORK_MAIN_BAT_DISCONNECT, 500);
break;
case STATE_KEY_IN:
// WakeUp 작업이 필요함
disp_keyState(oled, "KEY IN", "OFF");
// job_add(WORK_BOOSTER_CONNECT, 0);
// job_add(WORK_SUB_BAT_CONNECT, 0);
// job_add(WORK_SUPERCAP_DISCONNECT, 0);
// job_add(WORK_CHARGER_DISCONNECT, 0);
// job_add(WORK_JUMPSTART_DISCONNECT, 0);
// job_add(WORK_MAIN_BAT_DISCONNECT, 500);
break;
case STATE_KEY_ACC:
disp_keyState(oled, "ACC", "OFF");
// job_add(WORK_BOOSTER_CONNECT, 0);
// job_add(WORK_MAIN_BAT_CONNECT, 0);
// job_add(WORK_CHARGER_DISCONNECT, 0);
// job_add(WORK_SUPERCAP_DISCONNECT, 0);
// job_add(WORK_JUMPSTART_DISCONNECT, 0);
// job_add(WORK_SUB_BAT_DISCONNECT, 500);
// // if (old_keyState == KEY_IN) { // 시동 걸려고 할때
// // job_add(WORK_MAIN_BAT_CONNECT, 0);
// // job_add(WORK_SUB_BAT_DISCONNECT, 500);
// // }
// // if (old_keyState == KEY_ON) { // 시동을 껐을 때
// // job_add(WORK_CHARGER_DISCONNECT, 0);
// // job_add(WORK_SUPERCAP_DISCONNECT, 0);
// // }
break;
case STATE_KEY_ON:
disp_keyState(oled, "Key ON", "OFF");
// job_add(WORK_MAIN_BAT_CONNECT, 0);
// job_add(WORK_BOOSTER_DISCONNECT, 0);
// job_add(WORK_SUPERCAP_CONNECT, 0);
// job_add(WORK_CHARGER_DISCONNECT, 0);
// job_add(WORK_SUB_BAT_DISCONNECT, 0);
if (old_keyState == STATE_KEY_ACC) { // 시동 걸려고 할때
disp_keyState(oled, "ON READY", "OFF");
// job_add(WORK_SUPERCAP_CONNECT, 0);
}
if (old_keyState == STATE_KEY_START) {
if (engine_state == ON) { // 시동이 걸렸을 때
disp_keyState(oled1, "RUNNING", "ON");
// job_add(WORK_CHARGER_CONNECT, 0);
// job_add(WORK_JUMPSTART_DISCONNECT, 5000);
}
if (engine_state == OFF) { // 시동이 걸리지 않았을 때
disp_keyState(oled1, "Retry", "OFF");
}
}
// job_add(WORK_JUMPSTART_DISCONNECT, 0);
break;
case STATE_KEY_START:
disp_keyState(oled1, "START", ".....");
// job_add(WORK_JUMPSTART_CONNECT, 0);
// job_add(WORK_MAIN_BAT_CONNECT, 0);
// job_add(WORK_SUPERCAP_CONNECT, 0);
// job_add(WORK_BOOSTER_DISCONNECT, 0);
// job_add(WORK_SUB_BAT_DISCONNECT, 0);
// job_add(WORK_CHARGER_DISCONNECT, 0);
break;
}
}
// const char* conv_keyState(int keyState) {
// if (keyState == STATE_KEY_OUT) {
// return "KEY_OUT";
// }
// if (keyState == STATE_KEY_IN) {
// return "KEY_IN";
// }
// if (keyState == STATE_KEY_ACC) {
// return "KEY_ACC";
// }
// if (keyState == STATE_KEY_ON) {
// return "KEY_ON";
// }
// if (keyState == STATE_KEY_START) {
// return "KEY_START";
// }
// return "NONE";
// }
// void func_booster_select() {
// if (relay.booster.input == true) {
// if (batVolt.main > 9.0) {
// Serial.println("부스터입력 : 메인배터리 선택");
// PCF_02.write(RELAY_CON_BOOSTER_SELECT, LOW);
// relay.booster.select = MAIN;
// }
// else {
// Serial.println("부스터입력 : 보조배터리 선택");
// PCF_02.write(RELAY_CON_BOOSTER_SELECT, HIGH);
// relay.booster.select = SUB;
// }
// }
// else {
// Serial.println("부스터입력 : 메인배터리 선택");
// PCF_02.write(RELAY_CON_BOOSTER_SELECT, LOW);
// relay.booster.select = MAIN;
// }
// }
// void func_main_bat_connecting() {
// if (relay.main == false) {
// Serial.println("메인배터리 연결");
// PCF_01.write(RELAY_CON_MAIN, HIGH);
// // digitalWriteMux(MUX2, RELAY_CON_MAIN, HIGH);
// relay.main = true;
// }
// }
// void func_main_bat_disconnecting() {
// if (relay.main == true) {
// Serial.println("메인배터리 차단");
// PCF_01.write(RELAY_CON_MAIN, LOW);
// // digitalWriteMux(MUX2, RELAY_CON_MAIN, LOW);
// relay.main = false;
// }
// }
// void func_sub_bat_connecting() {
// if (relay.sub == false) {
// Serial.println("보조배터리 연결");
// PCF_01.write(RELAY_CON_SUB, HIGH);
// // digitalWriteMux(MUX2, RELAY_CON_SUB, HIGH);
// relay.sub = true;
// }
// }
// void func_sub_bat_disconnecting() {
// if (relay.sub == true) {
// Serial.println("보조배터리 차단");
// PCF_01.write(RELAY_CON_SUB, LOW);
// // digitalWriteMux(MUX2, RELAY_CON_SUB, LOW);
// relay.sub = false;
// }
// }
// void func_supercap_connecting() {
// if (relay.supercap == false) {
// Serial.println("수퍼캡 연결");
// PCF_01.write(RELAY_CON_SUPERCAP, HIGH);
// relay.supercap = true;
// }
// }
// void func_supercap_disconnecting() {
// if (relay.supercap == true) {
// Serial.println("수퍼캡 차단");
// PCF_01.write(RELAY_CON_SUPERCAP, LOW);
// relay.supercap = false;
// }
// }
// void func_jumpstarter_connecting() {
// if (relay.jumpstarter == false) {
// Serial.println("점프스타트 연결");
// PCF_01.write(RELAY_CON_JUMPSTARTER, HIGH);
// relay.jumpstarter = true;
// }
// }
// void func_jumpstarter_disconnecting() {
// if (relay.jumpstarter == true) {
// Serial.println("점프스타트 차단");
// PCF_01.write(RELAY_CON_JUMPSTARTER, LOW);
// relay.jumpstarter = false;
// }
// }
// void func_charger_connecting() {
// if (relay.charger == false) {
// Serial.println("충전회로 연결");
// PCF_01.write(RELAY_CON_CHARGER, HIGH);
// relay.charger = true;
// }
// }
// void func_charger_disconnecting() {
// if (relay.charger == true) {
// Serial.println("충전회로 차단");
// PCF_01.write(RELAY_CON_CHARGER, LOW);
// relay.charger = false;
// }
// }
// void func_booster_connecting() {
// if (relay.booster.input == false) {
// Serial.println("부스터/입력 연결");
// PCF_02.write(RELAY_CON_BOOSTER_INPUT, HIGH);
// relay.booster.input = true;
// func_booster_select();
// }
// }
// void func_booster_disconnecting() {
// if (relay.booster.input == true) {
// Serial.println("부스터/입력 차단");
// PCF_02.write(RELAY_CON_BOOSTER_INPUT, LOW);
// relay.booster.input = false;
// func_booster_select();
// }
// }
// void func_booster_output_state() {
// if (relay.booster.input == true) {
// switch(relay.booster.output) {
// case true:
// if (batVolt.booster.output >= 15.5) {
// Serial.println("부스터/출력 차단 (Over Volt)");
// PCF_02.write(RELAY_CON_BOOSTER_OUTPUT, LOW);
// relay.booster.output = false;
// }
// if (batVolt.booster.input < 9.0) {
// Serial.println("부스터/출력 차단 (Low Volt)");
// PCF_02.write(RELAY_CON_BOOSTER_INPUT, LOW);
// PCF_02.write(RELAY_CON_BOOSTER_OUTPUT, LOW);
// relay.booster.input = false;
// relay.booster.output = false;
// }
// break;
// case false:
// if (batVolt.booster.output < 15.5) {
// Serial.println("부스터/출력 연결");
// PCF_02.write(RELAY_CON_BOOSTER_OUTPUT, HIGH);
// relay.booster.output = true;
// }
// break;
// }
// }
// else {
// if (relay.booster.output == true) {
// Serial.println("부스터/출력 차단 (Not Input Command)");
// PCF_02.write(RELAY_CON_BOOSTER_OUTPUT, LOW);
// relay.booster.output = false;
// }
// }
// }
// void func_latching_set() {
// if (relay.latching == false) {
// Serial.println("래칭릴레이 세팅(ON)");
// PCF_01.write(RELAY_RACH_MAIN_ON, HIGH);
// delay(200);
// PCF_01.write(RELAY_RACH_MAIN_ON, LOW);
// relay.latching = true;
// }
// }
// void func_latching_reset() {
// if (relay.latching == true) {
// Serial.println("래칭릴레이 리셋(OFF)");
// PCF_01.write(RELAY_RACH_MAIN_OFF, HIGH);
// delay(200);
// PCF_01.write(RELAY_RACH_MAIN_OFF, LOW);
// relay.latching = false;
// }
// }
// void IRAM_ATTR Timer0_ISR() {
// digitalWrite(RELAY_CHARGER_SUPERCAP2, !digitalRead(RELAY_CHARGER_SUPERCAP2));
// Serial.println("타이머 작동");
// }
// void IRAM_ATTR func_sub_bat_disconnecting() {
// sub_func_sub_bat_disconnecting();
// timerAlarmDisable(Timer0_Cfg);
// }
void wake_up_msg() {
float temp_volt = read_volt(PIN_BTN_SLEEP);
// if (temp_volt > CHK_ON) {
if (digitalRead(PIN_BTN_SLEEP) == LOW) {
sleep_reserved = false;
// PCF_02.write(0, LOW);
//Increment boot number and print it every reboot
++bootCount;
Serial.println("Check Sleep Volt : " + String(temp_volt));
Serial.println("Boot number: " + String(bootCount));
//Print the wakeup reason for ESP32
print_wakeup_reason();
Serial.println("");
}
}
void go_sleep_now() {
esp_sleep_enable_ext0_wakeup(GPIO_NUM_27, 1); //1 = High, 0 = Low
//Go to sleep now
Serial.println("Going to sleep now");
delay(1000);
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void func_work_nextjob() {
switch(nextjob[0][0]) {
// case WORK_MAIN_BAT_CONNECT:
// func_main_bat_connecting();
// break;
// case WORK_MAIN_BAT_DISCONNECT:
// func_main_bat_disconnecting();
// break;
// case WORK_SUB_BAT_CONNECT:
// func_sub_bat_connecting();
// func_latching_set();
// break;
// case WORK_SUB_BAT_DISCONNECT:
// func_sub_bat_disconnecting();
// func_latching_reset();
// break;
// case WORK_SUPERCAP_CONNECT:
// func_supercap_connecting();
// break;
// case WORK_SUPERCAP_DISCONNECT:
// func_supercap_disconnecting();
// break;
// case WORK_JUMPSTART_CONNECT:
// func_jumpstart_connecting();
// break;
// case WORK_JUMPSTART_DISCONNECT:
// func_jumpstart_disconnecting();
// break;
// case WORK_CHARGER_CONNECT:
// func_charger_connecting();
// break;
// case WORK_CHARGER_DISCONNECT:
// func_charger_disconnecting();
// break;
// case WORK_BOOSTER_CONNECT:
// func_booster_connecting();
// break;
// case WORK_BOOSTER_DISCONNECT:
// func_booster_disconnecting();
// break;
case WORK_SLEEP_NOW:
go_sleep_now();
break;
default:
break;
}
// disp_keyState(oled1);
// disp_sleep_reserved(oled1);
job_pull();
}
void scan_i2c() {
byte error, address;
int nDevices;
Serial.println("Scanning...");
nDevices = 0;
for(address = 1; address < 127; address++) {
// The i2c-scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4) {
Serial.print("Unknown error at address 0x");
if (address<16) {
Serial.print("0");
}
Serial.println(address,HEX);
}
}
if (nDevices == 0) {
Serial.println("No I2C devices found\n");
} else {
Serial.println("done\n");
}
delay(2000); // wait 5 seconds for next scan
}
void convDataStruct_Sensor() {
// outgoingSetpoints.msgType = DATA;
// outgoingSetpoints.id = 0;
// outgoingSetpoints.temp = random(0, 40);
// outgoingSetpoints.hum = random(0, 100);
// outgoingSetpoints.readingId = counter++;
msg_Sensor.sid++;
msg_Sensor.msgType = DATA;
msg_Sensor.dataType = SENSOR;
msg_Sensor.bid = BOARD_ID;
msg_Sensor.sid = msg_Sensor.sid;
msg_Sensor.data.keyin = sensor.keyin;
msg_Sensor.data.cigarjack = sensor.cigarjack;
msg_Sensor.data.clock = sensor.clock;
msg_Sensor.data.ignition = sensor.ignition;
msg_Sensor.data.wiper = sensor.wiper;
msg_Sensor.data.airbag = sensor.airbag;
msg_Sensor.data.start = sensor.start;
}
void printDataStruct_Sensor() {
StaticJsonDocument<1000> root;
// msg_SensorVolt.id = 1;
// root["id"] = msg_SensorVolt.id;
// root["readingId"] = String(inData.readingId);
// root["relayNo"] = inData.relayNo;
// root["relayWork"] = inData.relayWork;
// msg_Sensor.msgType = DATA;
root["msgType"] = msg_Sensor.msgType;
root["dataType"] = msg_Sensor.dataType;
root["bid"] = msg_Sensor.bid;
root["sid"] = msg_Sensor.sid;
root["data"]["keyin"] = msg_Sensor.data.keyin;
root["data"]["cigarjack"] = msg_Sensor.data.cigarjack;
root["data"]["clock"] = msg_Sensor.data.clock;
root["data"]["ignition"] = msg_Sensor.data.ignition;
root["data"]["wiper"] = msg_Sensor.data.wiper;
root["data"]["airbag"] = msg_Sensor.data.airbag;
root["data"]["start"] = msg_Sensor.data.start;
Serial.print("Send Data : ");
serializeJson(root, Serial); // 받은데이터를 시리얼모니터에 json 방식으로 표시
Serial.println();
}
bool convDataStruct_Volt() {
bool ret_Value = false;
msg_batVolt = old_msg_batVolt;
msg_batVolt.data.main = (short)(batVolt.main * 100 + 0.5);
msg_batVolt.data.sub = (short)(batVolt.sub * 100 + 0.5);
msg_batVolt.data.booster.input = (short)(batVolt.booster.input * 100 + 0.5);
msg_batVolt.data.booster.output = (short)(batVolt.booster.output * 100 + 0.5);
msg_batVolt.data.supercap1 = (short)(batVolt.supercap1 * 100 + 0.5);
msg_batVolt.data.supercap2 = (short)(batVolt.supercap2 * 100 + 0.5);
if ((msg_batVolt.sid == 0)
or (msg_batVolt.data.main != old_msg_batVolt.data.main)
or (msg_batVolt.data.sub != old_msg_batVolt.data.sub)
or (msg_batVolt.data.booster.input != old_msg_batVolt.data.booster.input)
or (msg_batVolt.data.booster.output != old_msg_batVolt.data.booster.output)
or (msg_batVolt.data.supercap1 != old_msg_batVolt.data.supercap1)
or (msg_batVolt.data.supercap2 != old_msg_batVolt.data.supercap2)
) {
msg_batVolt.sid++;
msg_batVolt.msgType = DATA;
msg_batVolt.dataType = VOLT;
msg_batVolt.bid = BOARD_ID;
old_msg_batVolt = msg_batVolt;
ret_Value = true;
}
return ret_Value;
}
void printDataStruct_Volt() {
StaticJsonDocument<1000> root;
root["msgType"] = msg_batVolt.msgType;
root["dataType"] = msg_batVolt.dataType;
root["bid"] = msg_batVolt.bid;
root["sid"] = msg_batVolt.sid;
root["data"]["main"] = msg_batVolt.data.main;
root["data"]["sub"] = msg_batVolt.data.sub;
root["data"]["booster"]["input"] = msg_batVolt.data.booster.input;
root["data"]["booster"]["output"] = msg_batVolt.data.booster.output;
root["data"]["supercap1"] = msg_batVolt.data.supercap1;
root["data"]["supercap2"] = msg_batVolt.data.supercap2;
Serial.print("Send Data : ");
serializeJson(root, Serial); // 받은데이터를 시리얼모니터에 json 방식으로 표시
Serial.println();
}
bool convDataStruct_Ampere() {
bool ret_Value = false;
msg_Ampere = old_msg_Ampere;
msg_Ampere.data.self = (short)(ampere.self * 100 + 0.5);
msg_Ampere.data.main = (short)(ampere.main * 100 + 0.5);
msg_Ampere.data.sub = (short)(ampere.sub * 100 + 0.5);
msg_Ampere.data.booster = (short)(ampere.booster * 100 + 0.5);
msg_Ampere.data.supercap = (short)(ampere.supercap * 100 + 0.5);
msg_Ampere.data.jumpstarter = (short)(ampere.jumpstarter * 100 + 0.5);
if ((msg_Ampere.sid == 0)
or (msg_Ampere.data.self != old_msg_Ampere.data.self)
or (msg_Ampere.data.main != old_msg_Ampere.data.main)
or (msg_Ampere.data.sub != old_msg_Ampere.data.sub)
or (msg_Ampere.data.booster != old_msg_Ampere.data.booster)
or (msg_Ampere.data.supercap != old_msg_Ampere.data.supercap)
or (msg_Ampere.data.jumpstarter != old_msg_Ampere.data.jumpstarter)
) {
msg_Ampere.sid++;
msg_Ampere.msgType = DATA;
msg_Ampere.dataType = AMPERE;
msg_Ampere.bid = BOARD_ID;
old_msg_Ampere = msg_Ampere;
ret_Value = true;
}
return ret_Value;
}
void printDataStruct_Ampere() {
StaticJsonDocument<1000> root;
root["msgType"] = msg_Ampere.msgType;
root["dataType"] = msg_Ampere.dataType;
root["bid"] = msg_Ampere.bid;
root["sid"] = msg_Ampere.sid;
root["data"]["self"] = msg_Ampere.data.self;
root["data"]["main"] = msg_Ampere.data.main;
root["data"]["sub"] = msg_Ampere.data.sub;
root["data"]["booster"] = msg_Ampere.data.booster;
root["data"]["supercap"] = msg_Ampere.data.supercap;
root["data"]["jumpstarter"] = msg_Ampere.data.jumpstarter;
Serial.print("Send Data : ");
serializeJson(root, Serial); // 받은데이터를 시리얼모니터에 json 방식으로 표시
Serial.println();
}
bool convDataStruct_Check() {
bool ret_Value = false;
msg_RelayState = old_msg_RelayState;
msg_RelayState.data.main = relayState.main;
msg_RelayState.data.sub = relayState.sub;
msg_RelayState.data.supercap = relayState.supercap;
msg_RelayState.data.jumpstarter = relayState.jumpstarter;
msg_RelayState.data.latching = relayState.latching;
msg_RelayState.data.charger = relayState.charger;
msg_RelayState.data.booster.input = relayState.booster.input;
msg_RelayState.data.booster.output = relayState.booster.output;
if ((msg_RelayState.sid == 0)
or (msg_RelayState.data.main != old_msg_RelayState.data.main)
or (msg_RelayState.data.sub != old_msg_RelayState.data.sub)
or (msg_RelayState.data.supercap != old_msg_RelayState.data.supercap)
or (msg_RelayState.data.jumpstarter != old_msg_RelayState.data.jumpstarter)
or (msg_RelayState.data.latching != old_msg_RelayState.data.latching)
or (msg_RelayState.data.charger != old_msg_RelayState.data.charger)
or (msg_RelayState.data.booster.input != old_msg_RelayState.data.booster.input)
or (msg_RelayState.data.booster.output != old_msg_RelayState.data.booster.output)
) {
msg_RelayState.sid++;
msg_RelayState.msgType = DATA;
msg_RelayState.dataType = CHECK;
msg_RelayState.bid = BOARD_ID;
old_msg_RelayState = msg_RelayState;
ret_Value = true;
}
return ret_Value;
}
void printDataStruct_Check() {
StaticJsonDocument<1000> root;
root["msgType"] = msg_RelayState.msgType;
root["dataType"] = msg_RelayState.dataType;
root["bid"] = msg_RelayState.bid;
root["sid"] = msg_RelayState.sid;
root["data"]["main"] = msg_RelayState.data.main;
root["data"]["sub"] = msg_RelayState.data.sub;
root["data"]["supercap"] = msg_RelayState.data.supercap;
root["data"]["jumpstarter"] = msg_RelayState.data.jumpstarter;
root["data"]["latching"] = msg_RelayState.data.latching;
root["data"]["charger"] = msg_RelayState.data.charger;
root["data"]["booster"]["input"] = msg_RelayState.data.booster.input;
root["data"]["booster"]["output"] = msg_RelayState.data.booster.output;
Serial.print("Send Data : ");
serializeJson(root, Serial); // 받은데이터를 시리얼모니터에 json 방식으로 표시
Serial.println();
}
/*
=================================================================================
공통 라이브러리 종료
모듈별 프로그램 시작
=================================================================================
*/
void setup() {
Serial.begin(115200);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!oled1.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 OLED1 allocation failed"));
for (;;); // Don't proceed, loop forever
}
// if (!oled2.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
// Serial.println(F("SSD1306 OLED2 allocation failed"));
// for (;;); // Don't proceed, loop forever
// }
// if (!oled3.begin(SSD1306_SWITCHCAPVCC, 0x3E)) {
// Serial.println(F("SSD1306 OLED2 allocation failed"));
// for (;;); // Don't proceed, loop forever
// }
Serial.println("Start");
// mux_pin_init(MUX1);
// Serial.println("1");
// mux_pin_init(MUX2);
// pinMode(Mux_Pins[MUX2][COM], OUTPUT);
// Serial.println("2");
// pinMode(MUX1_S0, OUTPUT);
// pinMode(MUX1_S1, OUTPUT);
// pinMode(MUX1_S2, OUTPUT);
// pinMode(MUX1_S3, OUTPUT);
// pinMode(MUX2_S0, OUTPUT);
// pinMode(MUX2_S1, OUTPUT);
// pinMode(MUX2_S2, OUTPUT);
// pinMode(MUX2_S3, OUTPUT);
// pinMode(PIN_SENSOR_CIGAR, INPUT);
// pinMode(PIN_SENSOR_CLOCK, INPUT);
// pinMode(PIN_SENSOR_IG1, INPUT);
// pinMode(PIN_SENSOR_WIPER, INPUT);
// pinMode(PIN_SENSOR_AIRBAG, INPUT);
// pinMode(PIN_SENSOR_START, INPUT);
pinMode(PIN_SENSOR_KEY_IN, INPUT);
// pinMode(PIN_SENSOR_KEY_ACC, INPUT);
// pinMode(PIN_SENSOR_KEY_ON, INPUT);
// pinMode(PIN_SENSOR_KEY_IG1, INPUT);
// pinMode(PIN_SENSOR_KEY_IG2, INPUT);
// pinMode(PIN_SENSOR_KEY_START, INPUT);
pinMode(PIN_BTN_SLEEP, INPUT);
// pinMode(PIN_SENSOR_MAIN, INPUT);
// pinMode(PIN_SENSOR_SUB, INPUT);
// pinMode(PIN_SENSOR_BOOSTER, INPUT);
// pinMode(PIN_SENSOR_SUPERCAP1, INPUT);
// pinMode(PIN_SENSOR_SUPERCAP2, INPUT);
// pinMode(PIN_SENSOR_TYPE, INPUT);
// pinMode(PIN_SENSOR_CIGAR, INPUT);
// pinMode(PIN_SENSOR_CLOCK, INPUT);
// pinMode(PIN_SENSOR_AIRBAG, INPUT);
// pinMode(PIN_SENSOR_IG1, INPUT);
// pinMode(PIN_SENSOR_WIPER, INPUT);
// pinMode(PIN_SENSOR_START, INPUT);
// pinMode(PIN_SENSOR_DOORLOCK, INPUT);
pinMode(RELAY_CON_GND, OUTPUT);
// Serial.println("3");
digitalWrite(RELAY_CON_GND, HIGH);
// Serial.println("4");
delay(100);
PCF_01.begin();
PCF_01.write8(0b01010101);
int x = PCF_01.read8();
Serial.print("PCF_01 > Read : ");
Serial.println(x, HEX);
PCF_02.begin();
PCF_02.write8(0b10101010);
int y = PCF_02.read8();
Serial.print("PCF_02 > Read : ");
Serial.println(y, HEX);
variable_init();
display_start(oled1, MODULE_NAME, MODULE_NO1);
// display_start(oled2, MODULE_NAME, MODULE_NO2);
// display_start(oled3, MODULE_NAME, MODULE_NO3);
delay(1000);
oled1.clearDisplay();
oled1.display();
// oled2.clearDisplay();
// oled2.display();
// oled3.clearDisplay();
// oled3.display();
digitalWrite(RELAY_CON_GND, LOW);
wake_up_msg();
scan_i2c();
Serial.println("Raady!");
// digitalWriteMux(MUX2, RELAY_CON_MAIN, HIGH);
// Timer0_Cfg = timerBegin(0, 80, true);
}
void loop() {
char buf[80];
unsigned long now = millis();
// if (now - past_sleep >= time_delay_sleep_check) {
// past_sleep = now;
// flag_sleep = 1;
// }
if (digitalRead(PIN_BTN_SLEEP) == HIGH) {
if (sleep_reserved == false and read_volt(PIN_SENSOR_KEY_IN) < CHK_OFF) {
if (now - past_go_sleep >= time_delay_go_sleep) {
past_go_sleep = now;
flag_go_sleep = 1;
// WORK_SLEEP_NOW
// PCF_02.write(0, HIGH);
Serial.println("Deap Sleep Reserved");
sleep_reserved = true;
disp_sleep_reserved(oled1);
job_add(WORK_SLEEP_NOW, 10000);
// go_sleep_now();
}
}
if (sleep_reserved == true and read_volt(PIN_SENSOR_KEY_IN) > CHK_ON) {
Serial.println("Deap Sleep Relese");
sleep_reserved = false;
disp_sleep_reserved(oled1);
job_clear();
}
}
// if (now - past_key >= time_delay_key) {
// past_key = now;
// flag_key = 1;
// }
// if (now - past_volt >= time_delay_volt) {
// past_volt = now;
// flag_volt = 1;
// }
if (nextjob[0][0] == WORK_NONE) {
nextjob[0][1] = time_delay_nextwork;
}
if (now - past_nextwork >= nextjob[0][1]) {
past_nextwork = now;
flag_nextwork = 1;
}
// if (flag_volt == 1) {
// func_display_volt(oled1);
// func_display_current(oled2);
// // func_read_relayState_check_sensor();
// // func_booster_output_state();
// func_read_relayState_check_sensor();
// bool volt_changed = convDataStruct_Volt();
// if (volt_changed) printDataStruct_Volt();
// bool ampere_changed = convDataStruct_Ampere();
// if (ampere_changed) printDataStruct_Ampere();
// bool check_changed = convDataStruct_Check();
// if (check_changed) printDataStruct_Check();
// if (digitalRead(PIN_BTN_BLUETOOTH) == HIGH) {
// // 블루투스통신을 통해 자료 전송
// Serial.println("블루투스통신");
// }
// flag_volt = 0;
// }
if (flag_nextwork == 1) {
func_work_nextjob();
flag_nextwork = 0;
}
if (flag_key == 1) {
// func_check_state_logical();
// // for(uint8_t i = 0; i < 16; i++) {
// // int8_t channel = 0;
// int f = readMux(PIN_SENSOR_TYPE);
// // pixels.setPixelColor(i, pixels.Color(0, f / 4095.0 * 255.0, 0));
// Serial.print(PIN_SENSOR_TYPE);
// Serial.print(" = ");
// Serial.println(f);
// // }
// if (old_sensors_logic != sensors_logic) {
// func_set_netxjob(oled2);
// old_sensors_logic = sensors_logic;
// }
if (old_sensors_bit != sensors_bit) {
// func_set_netxjob(oled1);
convDataStruct_Sensor();
printDataStruct_Sensor();
if (digitalRead(PIN_BTN_BLUETOOTH) == HIGH) {
// 블루투스통신을 통해 자료 전송
Serial.println("블루투스통신");
}
old_sensors_bit = sensors_bit;
}
flag_key = 0;
}
//모니터 프로그램으로 입릭이 들어오면
if(Serial.available()){
String received_string = Serial.readStringUntil('\n');
int i = received_string.length();
char receivedChars[i+2];
strcpy(receivedChars, received_string.c_str());
Serial.println(receivedChars);
StaticJsonDocument<1000> filtre;
// filtre["yearRain_cm"] = true;
// filtre["UV"] = true;
filtre["msgType"] = true;
filtre["dataType"] = true;
filtre["bid"] = true;
filtre["sid"] = true;
filtre["data"]["main"] = true;
filtre["data"]["sub"] = true;
filtre["data"]["supercap"] = true;
filtre["data"]["jumpstarter"] = true;
filtre["data"]["latching"] = true;
filtre["data"]["charger"] = true;
filtre["data"]["booster"]["select"] = true;
filtre["data"]["booster"]["input"] = true;
filtre["data"]["booster"]["output"] = true;
size_t inputLength = strlen(receivedChars);
StaticJsonDocument<1000> doc;
DeserializationError error = deserializeJson(doc, receivedChars, inputLength, DeserializationOption::Filter(filtre));
if (error) {
Serial.print("erreur sur deserializeJson: ");
Serial.println(error.c_str());
return;
}
const char* sid = doc["sid"];
const char* data_main = doc["data"]["main"];
Serial.print("sid : "); Serial.println(sid); // ➜ 0.6 (sous format c-string, pas double)
Serial.print("data_main : "); Serial.println(data_main); // ➜ 26.359999839204004 (sous format c-string, pas double)
// double ubDouble = strtod(UV, nullptr);
// Serial.print("UV en nombre: "); Serial.println(ubDouble, 1); // ➜ 0.6 (sous format numérique avec 1 chiffre après la virgule à l'impression
// double cmDouble = strtod(yearRain_cm, nullptr);
// Serial.print("CM en nombre: "); Serial.println(cmDouble, 2); // ➜ 26.359999839204004 (sous format numérique avec 2 chiffres après la virgule à l'impression
}
sprintf(buf, "%d %d %d", now, past_nextwork, now - past_nextwork);
// Serial.println(buf);
}
// relay = {
// "msgType":1,
// "dataType":4,
// "bid":0,
// "sid":1,
// "data": {
// "main":true,
// "sub":true,
// "supercap":true,
// "jumpstarter":true,
// "latching":true,
// "charger":true,
// "booster": {
// "select":0,
// "input":true,
// "output":false
// }
// }
// }
// {"msgType":1,"dataType":4,"bid":0,"sid":1,"data": {"main":true,"sub":true,"supercap":true,"jumpstarter":true,"latching":true,"charger":true,"booster": {"select":0,"input":true,"output":false}}}주배터리
보조배터리
수퍼캡
점프스타터
메인래칭ON
메인래칭OFF
Charger
Booster/Before
보조배터리
주배터리
Booster/After
선택
Key In
Sleep
Bluetooth