Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- ESP32 Arduino sketch: toggle IDEC PLC Y0..Y7 over Maintenance Protocol (TCP/2101)
- Translates Python MiSmSerial Protocol:
- - Build msg: ENQ + device(2 ASCII) + '0' + 'W' + 'y' + addr(4 ASCII) + ('0'/'1')
- - BCC: XOR of all bytes in msg, appended as 2 ASCII hex chars
- - Append CR
- Notes:
- - PLC replies typically end with CR, so we read until '\r' or timeout.
- - This demo opens a new TCP connection per write (matches your Python).
- */
- #include <WiFi.h>
- const char* SSID = "Bangor Makerspace";
- const char* PASS = "UWishL0L";
- const char* PLC_IP = "10.1.0.175";
- const uint16_t PLC_PORT = 2101;
- // Device code is 2 ASCII hex chars in your frames (commonly "FF" or "00")
- const char* DEVICE = "FF";
- // ---------- Utility: XOR BCC, returned as 2 ASCII hex chars ----------
- static void bcc_xor_ascii_hex(const uint8_t* data, size_t len, char out2[2]) {
- uint8_t b = 0;
- for (size_t i = 0; i < len; i++) b ^= data[i];
- const char* hex = "0123456789ABCDEF";
- out2[0] = hex[(b >> 4) & 0x0F];
- out2[1] = hex[b & 0x0F];
- }
- // ---------- Read until CR or timeout ----------
- static size_t read_until_cr(WiFiClient& client, uint8_t* out, size_t out_cap, uint32_t timeout_ms) {
- size_t n = 0;
- uint32_t start = millis();
- while ((millis() - start) < timeout_ms && n < out_cap) {
- while (client.available() && n < out_cap) {
- int c = client.read();
- if (c < 0) break;
- out[n++] = (uint8_t)c;
- if ((uint8_t)c == '\r') return n;
- }
- delay(2);
- }
- return n;
- }
- // ---------- Transmit framed payload ----------
- static bool xmit(const char* ip, const uint8_t* payload, size_t payload_len,
- uint8_t* rx_buf, size_t rx_cap, size_t* rx_len,
- uint32_t timeout_ms = 2000) {
- WiFiClient client;
- client.setTimeout(timeout_ms / 1000.0f);
- if (!client.connect(ip, PLC_PORT)) {
- return false;
- }
- // Send
- size_t sent = client.write(payload, payload_len);
- client.flush();
- if (sent != payload_len) {
- client.stop();
- return false;
- }
- // Receive (until CR)
- *rx_len = read_until_cr(client, rx_buf, rx_cap, timeout_ms);
- client.stop();
- return true;
- }
- // ---------- Build + send "write y-bit" request ----------
- static bool write_y_bit(uint8_t bit_index, uint8_t value,
- uint8_t* rx_buf, size_t rx_cap, size_t* rx_len) {
- if (bit_index > 7) return false;
- if (value != 0 && value != 1) return false;
- // Message (without BCC/CR): ENQ + device(2) + '0' + 'W' + 'y' + addr(4) + val(1)
- // Total = 1 + 2 + 1 + 1 + 1 + 4 + 1 = 11 bytes
- uint8_t msg[11];
- size_t p = 0;
- msg[p++] = 0x05; // ENQ
- msg[p++] = (uint8_t)DEVICE[0]; // device 2 ASCII
- msg[p++] = (uint8_t)DEVICE[1];
- msg[p++] = (uint8_t)'0'; // continuation
- msg[p++] = (uint8_t)'W'; // command
- msg[p++] = (uint8_t)'y'; // datatype
- // addr as 4 ASCII digits, like Python f"{bit_index:04d}"
- char addr[5];
- snprintf(addr, sizeof(addr), "%04u", (unsigned)bit_index);
- msg[p++] = (uint8_t)addr[0];
- msg[p++] = (uint8_t)addr[1];
- msg[p++] = (uint8_t)addr[2];
- msg[p++] = (uint8_t)addr[3];
- msg[p++] = value ? (uint8_t)'1' : (uint8_t)'0';
- // Frame = msg + bcc(2 ascii) + CR
- uint8_t frame_buf[11 + 2 + 1];
- memcpy(frame_buf, msg, sizeof(msg));
- char bcc2[2];
- bcc_xor_ascii_hex(msg, sizeof(msg), bcc2);
- frame_buf[11] = (uint8_t)bcc2[0];
- frame_buf[12] = (uint8_t)bcc2[1];
- frame_buf[13] = (uint8_t)'\r';
- return xmit(PLC_IP, frame_buf, sizeof(frame_buf), rx_buf, rx_cap, rx_len);
- }
- // ---------- Pretty-print bytes ----------
- static void print_bytes(const uint8_t* b, size_t n) {
- Serial.print("b'");
- for (size_t i = 0; i < n; i++) {
- uint8_t c = b[i];
- if (c >= 32 && c <= 126 && c != '\\' && c != '\'') {
- Serial.write(c);
- } else {
- Serial.print("\\x");
- const char* hex = "0123456789abcdef";
- Serial.print(hex[(c >> 4) & 0x0F]);
- Serial.print(hex[c & 0x0F]);
- }
- }
- Serial.println("'");
- }
- void setup() {
- Serial.begin(115200);
- delay(200);
- WiFi.mode(WIFI_STA);
- WiFi.begin(SSID, PASS);
- Serial.print("WiFi connecting");
- while (WiFi.status() != WL_CONNECTED) {
- delay(300);
- Serial.print(".");
- }
- Serial.println();
- Serial.print("WiFi OK, IP: ");
- Serial.println(WiFi.localIP());
- // Optional: basic TCP connectivity check
- WiFiClient probe;
- if (probe.connect(PLC_IP, PLC_PORT)) {
- Serial.println("PLC port 2101 open (TCP connect OK).");
- probe.stop();
- } else {
- Serial.println("PLC port 2101 connect failed.");
- }
- }
- void loop() {
- static uint32_t last_run = 0;
- if (millis() - last_run < 1000) return;
- last_run = millis();
- uint8_t rx[256];
- size_t rx_len = 0;
- // Turn outputs ON 0..7
- for (uint8_t i = 0; i < 8; i++) {
- bool ok = write_y_bit(i, 1, rx, sizeof(rx), &rx_len);
- Serial.print("TX: set Y"); Serial.print(i); Serial.print("=1 -> ");
- if (!ok) {
- Serial.println("RX: (send/connect failed)");
- } else {
- Serial.print("RX: ");
- print_bytes(rx, rx_len);
- }
- delay(1000);
- }
- delay(1000);
- // Turn outputs OFF 7..0
- for (int i = 7; i >= 0; i--) {
- bool ok = write_y_bit((uint8_t)i, 0, rx, sizeof(rx), &rx_len);
- Serial.print("TX: set Y"); Serial.print(i); Serial.print("=0 -> ");
- if (!ok) {
- Serial.println("RX: (send/connect failed)");
- } else {
- Serial.print("RX: ");
- print_bytes(rx, rx_len);
- }
- delay(1000);
- }
- // Pause before repeating
- delay(2000);
- }
Advertisement
Add Comment
Please, Sign In to add comment