Hi, here is my code for SCPI controlled 6-Relay board. this is useful if you use it in automation without WIFI. It is adapted to use this PCF8574_library provided by kincony - where pins are enumerated by P0 .. P5
Code:
#include <Wire.h>
#include "PCF8574.h"
#include <esp_system.h> // For ESP.getEfuseMac()
#include <Preferences.h>
Preferences preferences;
// Set i2c address
PCF8574 pcf8574(0x24,4,15);
uint8_t portState = 0x0; // Ausgangszustand (alle Pins HIGH, 6 Pins genutzt)
const char* deviceID = "ESP32 + WiFi + LoRa/nRF24L01 + I2C + 2xADC + 4xDAC + 6xDI + 1 wire + GPIOs relay board";
uint32_t chipId = 0;
void setup() {
Serial.begin(9600);
// Print startup messages
Serial.println("started...");
delay(300);
Serial.print("compiled: ");
Serial.print(__DATE__);
Serial.print(" ");
Serial.println(__TIME__);
Serial.print("file: ");
Serial.println(__FILE__);
pcf8574.begin();
// Set pinMode to OUTPUT
pcf8574.pinMode(P0, OUTPUT);
pcf8574.pinMode(P1, OUTPUT);
pcf8574.pinMode(P2, OUTPUT);
pcf8574.pinMode(P3, OUTPUT);
pcf8574.pinMode(P4, OUTPUT);
pcf8574.pinMode(P5, OUTPUT);
// Read and store the chip ID
for (int i = 0; i < 17; i = i + 8) {
chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i;
}
updatePCF8574(); // Initialzustand setzen
loadPortStateFromFlash(); // Initialzustand laden
printManual();
}
void loop() {
if (Serial.available()) {
String command = Serial.readStringUntil('\n');
command.trim();
command.toUpperCase(); // Unterstützt Kleinbuchstaben in Befehlen
handleSCPICommand(command);
}
}
void handleSCPICommand(String command) {
if (command.startsWith("SET")) {
int pin;
int value;
if (sscanf(command.c_str(), "SET %d %d", &pin, &value) == 2) {
if (pin >= 0 && pin < 6 && (value == 0 || value == 1)) {
setPinState(pin, value);
Serial.println("OK");
} else {
Serial.println("ERROR: Invalid pin or value");
}
} else {
Serial.println("ERROR: Invalid command format");
}
}
else if (command.startsWith("ALL")) {
int state;
if (sscanf(command.c_str(), "ALL %d", &state) == 1 && (state == 0 || state == 1)) {
if (state == 0) {
portState = 0x0;
updatePCF8574();
Serial.println("OK - all set to 0");
} else if (state == 1) {
portState = 0x3F;
updatePCF8574();
Serial.println("OK - all set to 1");
}
} else {
Serial.println("ERROR: Invalid state");
}
}
else if (command.equals("READ")) {
Serial.print("PORTSTATE: ");
for (int i = 5; i >= 0; i--) {
Serial.print(bitRead(portState, i));
}
Serial.println();
}
else if (command.equals("*IDN?")) {
Serial.println(deviceID);
}
else if (command.equals("SN?")) {
Serial.println(chipId);
}
else if (command.startsWith("GET")) {
int pin;
if (sscanf(command.c_str(), "GET %d", &pin) == 1 && pin >= 0 && pin < 6) {
Serial.print("Pin ");
Serial.print(pin);
Serial.print(": ");
Serial.println(bitRead(portState, pin));
} else {
Serial.println("ERROR: Invalid pin");
}
}
else if (command.startsWith("TGL")) {
int pin;
if (sscanf(command.c_str(), "TGL %d", &pin) == 1 && pin >= 0 && pin < 6) {
int currentState = bitRead(portState, pin);
setPinState(pin, !currentState);
Serial.println("OK");
} else {
Serial.println("ERROR: Invalid pin");
}
}
else if (command.equals("SAVE")) {
savePortStateToFlash();
Serial.println("OK: State saved");
}
else if (command.equals("LOAD")) {
loadPortStateFromFlash();
updatePCF8574();
Serial.println("OK: State loaded and set");
}
else if (command.equals("DEMO")) {
Serial.println("OK: running demo");
demo();
}
else if (command.equals("HELP") or command.equals("MANUAL")) {
printManual();
}
else {
Serial.println("ERROR: Unknown command");
}
}
void setPinState(int pin, int state) {
bitWrite(portState, pin, state);
switch (pin) {
case 0: pcf8574.digitalWrite(P0, state); break;
case 1: pcf8574.digitalWrite(P1, state); break;
case 2: pcf8574.digitalWrite(P2, state); break;
case 3: pcf8574.digitalWrite(P3, state); break;
case 4: pcf8574.digitalWrite(P4, state); break;
case 5: pcf8574.digitalWrite(P5, state); break;
}
}
void updatePCF8574() {
pcf8574.digitalWrite(P0, bitRead(portState, 0));
pcf8574.digitalWrite(P1, bitRead(portState, 1));
pcf8574.digitalWrite(P2, bitRead(portState, 2));
pcf8574.digitalWrite(P3, bitRead(portState, 3));
pcf8574.digitalWrite(P4, bitRead(portState, 4));
pcf8574.digitalWrite(P5, bitRead(portState, 5));
}
void demo() { // Initial pin toggle
uint8_t state = portState;
for (int i = 0; i < 6; i++) {
setPinState(i, HIGH);
delay(300);
setPinState(i, LOW);
delay(300);
}
portState = state;
updatePCF8574();
}
void printManual() {
Serial.println("SCPI Command Manual:");
Serial.println("*IDN? - Returns device identification");
Serial.println("SN? - Returns device serial number");
Serial.println("SET <pin> <state> - Sets the specified pin (0-5) to the value (0 or 1)");
Serial.println("GET <pin> - Returns the state of the specified pin");
Serial.println("TGL <pin> - Toggles the state of the specified pin");
Serial.println("ALL <state> - Sets all pins to the value (0 or 1)");
Serial.println("READ - Returns the port state in binary");
Serial.println("SAVE - Saves the current port state to FLASH - also serves as initial state");
Serial.println("LOAD - Loads the port state from FLASH");
Serial.println("DEMO - demonstrate all Relays");
Serial.println("HELP - display this information");
Serial.println();
}
bool writeToFlash(const char* key, uint8_t value) {
// Open preferences with namespace "storage"
if (!preferences.begin("storage", false)) { // false = RW mode
Serial.println("Failed to open preferences");
return false;
}
// Write the value
preferences.putUChar(key, value);
// Close the preferences
preferences.end();
return true;
}
void savePortStateToFlash() {
// Placeholder function to save port state to FLASH
// Implementation depends on the specific microcontroller and storage library
// Function to write 8-bit value to flash
if (writeToFlash("Key_PortState", portState)) {
Serial.println("Successfully wrote to flash");
}
}
uint8_t readFromFlash(const char* key, uint8_t defaultValue = 0) {
// Open preferences with namespace "storage"
if (!preferences.begin("storage", true)) { // true = read-only mode
Serial.println("Failed to open preferences");
return defaultValue;
}
// Read the value with default if key doesn't exist
uint8_t value = preferences.getUChar(key, defaultValue);
// Close the preferences
preferences.end();
return value;
}
void loadPortStateFromFlash() {
// Placeholder function to load port state from FLASH
// Implementation depends on the specific microcontroller and storage library
// Read from flash
portState = readFromFlash("Key_PortState");
Serial.print("Read value: ");
for (int i = 5; i >= 0; i--) {
Serial.print(bitRead(portState, i));
};
Serial.println("");
//updatePCF8574();
}