From 020789e362662a77fd629b0a83811935fc63cb77 Mon Sep 17 00:00:00 2001 From: Ole Artz Date: Thu, 17 Mar 2022 11:13:49 +0100 Subject: [PATCH] LANTelnetToI2C_Board: implement a 0.91 OLED Display for on board monitoring w/ IP- and MAC-address, live plot and re-plot w/ python of the measured vals, quickstart manual for settings --- .../LANTelnetToI2C_Board.ino | 801 +++++++++++------- .../live_telnet_data_plot.py | 98 +++ ...kstart 4CH ADC_Ethernet Portable Board.pdf | Bin 0 -> 60237 bytes .../LANTelnetToI2C_Board/telnet_data_plot.py | 86 ++ 4 files changed, 677 insertions(+), 308 deletions(-) create mode 100644 esp32/EthernetUART/LANTelnetToI2C_Board/live_telnet_data_plot.py create mode 100644 esp32/EthernetUART/LANTelnetToI2C_Board/quickstart 4CH ADC_Ethernet Portable Board.pdf create mode 100644 esp32/EthernetUART/LANTelnetToI2C_Board/telnet_data_plot.py diff --git a/esp32/EthernetUART/LANTelnetToI2C_Board/LANTelnetToI2C_Board.ino b/esp32/EthernetUART/LANTelnetToI2C_Board/LANTelnetToI2C_Board.ino index bd0f402..8363a5b 100644 --- a/esp32/EthernetUART/LANTelnetToI2C_Board/LANTelnetToI2C_Board.ino +++ b/esp32/EthernetUART/LANTelnetToI2C_Board/LANTelnetToI2C_Board.ino @@ -5,16 +5,17 @@ # ### for START TELNET SERVER ### # # ### for LAN to I2C ### # # ### connected to 4 CH ADC ### # +# ### connected to 0.91 OLED Display ### # # ### ### # # ### author: O.Artz ### # # ### ### # -# ### UPDATE 2021-07-01 ### # +# ### UPDATE 2022-01-20 ### # # ### ### # ##################################################### -ETH MAC: 24:6F:28:1E:C5:57 -IPv4: 192.168.8.64 -Telnet: 192.168.8.64 2323 +ETH MAC: 24:6F:28:1E:C7:DF +IPv4: 192.168.8.63 +Telnet: 192.168.8.63 2323 Visual Status via Board LEDs: ETH Start -> Green LED blink for 1 sec @@ -22,25 +23,25 @@ Telnet work -> Green LED on ETH Disconnected/stopped -> Orange LED on */ -//load needed Libaries -#include //for Telnet Server Connection -#include //for I2C Connection -#include //for external ADC +// load needed Libaries +#include //for external ADC +#include //for Telnet Server Connection +#include //for I2C Connection //__________________________________________ -#include //for display control -#include //for OLED display driver +#include //for OLED display driver +#include //for display control -//for screen +// for screen #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 32 // 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. +// The pins for I2C are defined by the Wire-library. // On an arduino UNO: A4(SDA), A5(SCL) // On an arduino MEGA 2560: 20(SDA), 21(SCL) // On an arduino LEONARDO: 2(SDA), 3(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 +#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 NUMFLAKES 10 // Number of snowflakes in the animation example @@ -48,189 +49,232 @@ Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); #define imageWidth 106 #define imageHeight 32 -const unsigned char logo_bmp [] PROGMEM = -{ -0xfc, 0x0f, 0xc0, 0x03, 0xf8, 0x3f, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x80, 0xfc, 0x0f, - 0xc0, 0x07, 0xf8, 0x3f, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x0f, 0xc0, 0x0f, - 0xf0, 0x3f, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x40, 0xfc, 0x0f, 0xc0, 0x1f, 0xe0, 0x3f, - 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xfc, 0xc0, 0xfc, 0x0f, 0xc0, 0x3f, 0xc0, 0x3f, 0xff, 0xfc, - 0x0f, 0xff, 0xff, 0xff, 0xf1, 0xc0, 0xfc, 0x0f, 0xc0, 0x3f, 0x80, 0x3f, 0x00, 0x00, 0x0f, 0xff, - 0xff, 0xff, 0xe7, 0xc0, 0xfc, 0x0f, 0xc0, 0x7f, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, - 0x8f, 0xc0, 0xfc, 0x0f, 0xc0, 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x3f, 0xc0, - 0xfc, 0x0f, 0xc1, 0xfc, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0xff, 0xc0, 0xfc, 0x0f, - 0xc3, 0xf8, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf1, 0xff, 0xc0, 0xfc, 0x0f, 0xc7, 0xf8, - 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x8f, 0xff, 0xc0, 0xfc, 0x0f, 0xcf, 0xf0, 0x00, 0x3f, - 0x00, 0x00, 0x0f, 0xff, 0xfc, 0x3f, 0xff, 0xc0, 0xfc, 0x0f, 0xcf, 0xe0, 0x00, 0x3f, 0x00, 0x00, - 0x0f, 0xff, 0xe0, 0xff, 0xff, 0xc0, 0xfc, 0x0f, 0xdf, 0xe0, 0x00, 0x3f, 0xff, 0xf0, 0x0f, 0xfe, - 0x0f, 0xff, 0xff, 0xc0, 0xfc, 0x0f, 0xff, 0xf0, 0x00, 0x3f, 0xff, 0xf0, 0x0f, 0x80, 0xff, 0xff, - 0xff, 0xc0, 0xfc, 0x0f, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfc, 0x0f, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0, 0xfc, 0x0f, - 0xfd, 0xfc, 0x00, 0x3f, 0xff, 0xf0, 0x0f, 0xf8, 0x1f, 0xff, 0xff, 0xc0, 0xfc, 0x0f, 0xf8, 0xfc, - 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xc1, 0xff, 0xff, 0xc0, 0xfc, 0x0f, 0xf0, 0xfe, 0x00, 0x3f, - 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x7f, 0xff, 0xc0, 0xfc, 0x0f, 0xe0, 0x7f, 0x00, 0x3f, 0x00, 0x00, - 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xc0, 0xfc, 0x0f, 0xe0, 0x7f, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, - 0xff, 0xe3, 0xff, 0xc0, 0xfc, 0x0f, 0xc0, 0x3f, 0x80, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf8, - 0xff, 0xc0, 0xfc, 0x0f, 0xc0, 0x3f, 0x80, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfe, 0x3f, 0xc0, - 0xfc, 0x0f, 0xc0, 0x1f, 0xc0, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x9f, 0xc0, 0xfc, 0x0f, - 0xc0, 0x0f, 0xe0, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xc7, 0xc0, 0xfc, 0x0f, 0xc0, 0x0f, - 0xe0, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xf3, 0xc0, 0xfc, 0x0f, 0xc0, 0x07, 0xf0, 0x3f, - 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xf9, 0xc0, 0xfc, 0x0f, 0xc0, 0x07, 0xf0, 0x3f, 0x00, 0x00, - 0x0f, 0xff, 0xff, 0xff, 0xfc, 0xc0, 0xfc, 0x0f, 0xc0, 0x03, 0xf8, 0x3f, 0x00, 0x00, 0x0f, 0xff, - 0xff, 0xff, 0xfe, 0x40, 0xfc, 0x0f, 0xc0, 0x03, 0xfc, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, - 0xff, 0x00, 0xfc, 0x0f, 0xc0, 0x01, 0xfc, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x80 -}; +const unsigned char logo_bmp[] PROGMEM = { + 0xfc, 0x0f, 0xc0, 0x03, 0xf8, 0x3f, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0x80, 0xfc, 0x0f, 0xc0, 0x07, 0xf8, 0x3f, 0xff, 0xfc, 0x0f, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xfc, 0x0f, 0xc0, 0x0f, 0xf0, 0x3f, 0xff, 0xfc, + 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x40, 0xfc, 0x0f, 0xc0, 0x1f, 0xe0, 0x3f, + 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xfc, 0xc0, 0xfc, 0x0f, 0xc0, 0x3f, + 0xc0, 0x3f, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xf1, 0xc0, 0xfc, 0x0f, + 0xc0, 0x3f, 0x80, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xe7, 0xc0, + 0xfc, 0x0f, 0xc0, 0x7f, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, + 0x8f, 0xc0, 0xfc, 0x0f, 0xc0, 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, + 0xff, 0xff, 0x3f, 0xc0, 0xfc, 0x0f, 0xc1, 0xfc, 0x00, 0x3f, 0x00, 0x00, + 0x0f, 0xff, 0xff, 0xfc, 0xff, 0xc0, 0xfc, 0x0f, 0xc3, 0xf8, 0x00, 0x3f, + 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf1, 0xff, 0xc0, 0xfc, 0x0f, 0xc7, 0xf8, + 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x8f, 0xff, 0xc0, 0xfc, 0x0f, + 0xcf, 0xf0, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xfc, 0x3f, 0xff, 0xc0, + 0xfc, 0x0f, 0xcf, 0xe0, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0xff, + 0xff, 0xc0, 0xfc, 0x0f, 0xdf, 0xe0, 0x00, 0x3f, 0xff, 0xf0, 0x0f, 0xfe, + 0x0f, 0xff, 0xff, 0xc0, 0xfc, 0x0f, 0xff, 0xf0, 0x00, 0x3f, 0xff, 0xf0, + 0x0f, 0x80, 0xff, 0xff, 0xff, 0xc0, 0xfc, 0x0f, 0xff, 0xf8, 0x00, 0x3f, + 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0xff, 0xf8, + 0x00, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc0, 0xfc, 0x0f, + 0xfd, 0xfc, 0x00, 0x3f, 0xff, 0xf0, 0x0f, 0xf8, 0x1f, 0xff, 0xff, 0xc0, + 0xfc, 0x0f, 0xf8, 0xfc, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xc1, 0xff, + 0xff, 0xc0, 0xfc, 0x0f, 0xf0, 0xfe, 0x00, 0x3f, 0x00, 0x00, 0x0f, 0xff, + 0xf8, 0x7f, 0xff, 0xc0, 0xfc, 0x0f, 0xe0, 0x7f, 0x00, 0x3f, 0x00, 0x00, + 0x0f, 0xff, 0xff, 0x0f, 0xff, 0xc0, 0xfc, 0x0f, 0xe0, 0x7f, 0x00, 0x3f, + 0x00, 0x00, 0x0f, 0xff, 0xff, 0xe3, 0xff, 0xc0, 0xfc, 0x0f, 0xc0, 0x3f, + 0x80, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf8, 0xff, 0xc0, 0xfc, 0x0f, + 0xc0, 0x3f, 0x80, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfe, 0x3f, 0xc0, + 0xfc, 0x0f, 0xc0, 0x1f, 0xc0, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, + 0x9f, 0xc0, 0xfc, 0x0f, 0xc0, 0x0f, 0xe0, 0x3f, 0x00, 0x00, 0x0f, 0xff, + 0xff, 0xff, 0xc7, 0xc0, 0xfc, 0x0f, 0xc0, 0x0f, 0xe0, 0x3f, 0x00, 0x00, + 0x0f, 0xff, 0xff, 0xff, 0xf3, 0xc0, 0xfc, 0x0f, 0xc0, 0x07, 0xf0, 0x3f, + 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xf9, 0xc0, 0xfc, 0x0f, 0xc0, 0x07, + 0xf0, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xfc, 0xc0, 0xfc, 0x0f, + 0xc0, 0x03, 0xf8, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x40, + 0xfc, 0x0f, 0xc0, 0x03, 0xfc, 0x3f, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0x00, 0xfc, 0x0f, 0xc0, 0x01, 0xfc, 0x3f, 0x00, 0x00, 0x0f, 0xff, + 0xff, 0xff, 0xff, 0x80}; //__________________________________________ -//how many clients should be able to telnet to this ESP32 +// how many clients should be able to telnet to this ESP32 #define MAX_SRV_CLIENTS 10 #define SDA 5 #define SCL 32 -#define ISMYADDR() (rxbuf[1] == '0' && (rxbuf[2] == '0' )) //|| rxbuf[2] == '1' || rxbuf[2] == '2' || rxbuf[2] == '3') ) +#define ISMYADDR() (rxbuf[1] == '0' && (rxbuf[2] == '0')) //|| rxbuf[2] == '1' || rxbuf[2] == '2' || rxbuf[2] == '3') ) -Adafruit_ADS1115 ads(0x48); /* Use this for the 16-Bit version */ +Adafruit_ADS1115 ads(0x48); //Use this for the 16-Bit version WiFiServer server(2323); WiFiClient serverClients[MAX_SRV_CLIENTS]; -//used to check the number every time, cause could changed +// used to check the number every time, cause could changed volatile static bool eth_connected = false; +bool show_connection = true; uint8_t rxcnt = 0, txpoint = 0; -uint8_t rxbuf[11]; -uint8_t txbuf[12]; -uint8_t val, new_gain; +uint8_t rxbuf[11], txbuf[12]; +uint8_t val, new_gain, new_unit; +float vol_div_fac, dev_trans_fac; +uint16_t new_vol_div_fac, new_dev_trans_fac; int16_t adc0, adc1, adc2, adc3; float fadc0, fadc1, fadc2, fadc3; +float offset0, offset1, offset2, offset3; +int16_t new_offset_val; +int chan_offset_num, offset_val; uint8_t setGAIN = 0xFFFF; float setADCconversion; float acGAIN[] = {0.1875, 0.125, 0.0625, 0.03125, 0.015625, 0.0078125}; adsGain_t asetGAIN[] = {GAIN_TWOTHIRDS, GAIN_ONE, GAIN_TWO, GAIN_FOUR, GAIN_EIGHT, GAIN_SIXTEEN}; int counter = 0; - - -void WiFiEvent(WiFiEvent_t event) -{ - switch (event){ - case SYSTEM_EVENT_ETH_START: - Serial.println("ETH Started"); - //set eth hostname here - digitalWrite(2,LOW); - digitalWrite(15,HIGH); - delay(500); - digitalWrite(15, LOW); - ETH.setHostname("esp32-ethernet"); - break; - - case SYSTEM_EVENT_ETH_CONNECTED: - Serial.println("ETH Connected"); - digitalWrite(2,LOW); - digitalWrite(15,HIGH); - break; - - case SYSTEM_EVENT_ETH_GOT_IP: - Serial.print("ETH MAC: "); - Serial.print(ETH.macAddress()); - Serial.print(", IPv4: "); - Serial.print(ETH.localIP()); - if (ETH.fullDuplex()) { - Serial.print(", FULL_DUPLEX"); - } - Serial.print(", "); - Serial.print(ETH.linkSpeed()); - Serial.println("Mbps"); - eth_connected = true; - break; - - case SYSTEM_EVENT_ETH_DISCONNECTED: - Serial.println("ETH Disconnected"); - digitalWrite(15,LOW); - digitalWrite(2,HIGH); - eth_connected = false; - break; - - case SYSTEM_EVENT_ETH_STOP: - Serial.println("ETH Stopped"); - digitalWrite(15,LOW); - digitalWrite(2,HIGH); - eth_connected = false; - break; - - default: - break; +String possible_units[] = {"mV", "mA", "mbar", "degC"}; +String unit; + +void WiFiEvent(WiFiEvent_t event) { + switch (event) { + case SYSTEM_EVENT_ETH_START: + Serial.println("ETH Started"); + // set eth hostname here + digitalWrite(2, LOW); + digitalWrite(15, HIGH); + delay(500); + digitalWrite(15, LOW); + ETH.setHostname("esp32-ethernet"); + break; + + case SYSTEM_EVENT_ETH_CONNECTED: + Serial.println("ETH Connected"); + digitalWrite(2, LOW); + digitalWrite(15, HIGH); + break; + + case SYSTEM_EVENT_ETH_GOT_IP: + Serial.print("ETH MAC: "); + Serial.print(ETH.macAddress()); + Serial.print(", IPv4: "); + Serial.print(ETH.localIP()); + if (ETH.fullDuplex()) { + Serial.print(", FULL_DUPLEX"); + } + Serial.print(", "); + Serial.print(ETH.linkSpeed()); + Serial.println("Mbps"); + eth_connected = true; + break; + + case SYSTEM_EVENT_ETH_DISCONNECTED: + Serial.println("ETH Disconnected"); + digitalWrite(15, LOW); + digitalWrite(2, HIGH); + eth_connected = false; + break; + + case SYSTEM_EVENT_ETH_STOP: + Serial.println("ETH Stopped"); + digitalWrite(15, LOW); + digitalWrite(2, HIGH); + eth_connected = false; + break; + + default: + break; } } -void setup(){ -//for Telnet Server Connection - pinMode(2, OUTPUT); // yellow LED - pinMode(15, OUTPUT); // green LED +void start_telnet() { + // for Telnet Server Connection + pinMode(2, OUTPUT); // yellow LED + pinMode(15, OUTPUT); // green LED Serial.begin(115200); Serial.println("\nConnecting"); + WiFi.onEvent(WiFiEvent); delay(1000); - //start UART and the server - ETH.begin(1,17,23,18,ETH_PHY_LAN8720,ETH_CLOCK_GPIO0_IN); + // start UART and the server + ETH.begin(1, 17, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_IN); server.begin(); server.setNoDelay(true); - while (eth_connected == false); - Serial.print("Ready! Use 'telnet "); Serial.print(ETH.localIP()); Serial.println(" 2323' to connect"); - //visual status for telnet work - digitalWrite(2,LOW); - digitalWrite(15,HIGH); + // visual status for telnet work + digitalWrite(2, LOW); + digitalWrite(15, HIGH); +} -//for I2C Connection +void setup() { + start_telnet(); + // for I2C Connection Wire.begin(SDA, SCL); // Initiate the Wire library - //Setting for external ADC measurment range - // val ADS1015 ADS1115 - // ------- ------- - // 0 ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV - // 1 ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV - // 2 ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV - // 3 ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV - // 4 ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV - // 5 ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV - - val = 2; //chose as default for external adc setting - set_adc_gain(val); + // for display__________________________________________________________ + restart_screen(); + start_screen(); + connection_screen(); + // test_screen(); + +//Setting for external ADC measurment range +// val ADS1015 ADS1115 +// ------- ------- +// 0 ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV +// 1 ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV +// 2 ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV +// 3 ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV +// 4 ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV +// 5 ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV + + val = 2; // chose as default for external adc setting + set_adc_gain(val); + +// Chose right Unit +// val Unit +// 0 mV +// 1 mA +// 2 mbar +// 3 degC + + new_unit = 0; //default mV + set_unit(new_unit); + +// Channel Offset + new_offset_val = 0; //default + chan_offset_num = 5; //default all channels + set_offset(new_offset_val, chan_offset_num); + +// Device Transformationfactor + new_dev_trans_fac = 1000; //default + set_device_transformation_factor(new_dev_trans_fac); + +// Input voltage divider + new_vol_div_fac = 1000; //default w/o voltage devider, 1000 cause will devider by 1000 to sent float by telnet + set_voltage_divider_factor(new_vol_div_fac); Serial.print("\nADC Settings"); - Serial.print("\nActual Gainfactor: "); Serial.print(asetGAIN[val]); - Serial.print("\nConversionfactor: "); Serial.print(setADCconversion); Serial.println(); + Serial.print("\nActual Gainfactor: "); + Serial.print(asetGAIN[val]); + Serial.print("\nConversionfactor: "); + Serial.print(setADCconversion); + Serial.println(); -//for display__________________________________________________________ - restart_screen(); - start_screen(); - //test_screen(); } void restart_screen() { // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally - if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS, false, false)) { + if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS, false, false)) { Serial.println(F("SSD1306 allocation failed")); - for(;;); // Don't proceed, loop forever + for (;;); // Don't proceed, loop forever } // Show initial display buffer contents on the screen -- // the library initializes this with an Adafruit splash screen. - //display.display(); - + // display.display(); + delay(1000); // Pause for 2 seconds display.clearDisplay(); } -void start_screen() { +void start_screen() { display.clearDisplay(); - display.setTextSize(1); // Normal 1:1 pixel scale + display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text - display.cp437(true); // Use full 256 char 'Code Page 437' font + display.cp437(true); // Use full 256 char 'Code Page 437' font display.drawBitmap(0, 0, logo_bmp, imageWidth, imageHeight, SSD1306_WHITE); display.setCursor(108, 0); @@ -241,17 +285,36 @@ void start_screen() { display.write("J.M."); display.setCursor(108, 24); display.write("O.A."); - + display.display(); - delay(3000); // Pause for 2 seconds - } + delay(3000); // Pause for 3 seconds +} + +void connection_screen() { + display.clearDisplay(); + display.setTextSize(1); // Normal 1:1 pixel scale + display.setTextColor(SSD1306_WHITE); // Draw white text + display.cp437(true); // Use full 256 char 'Code Page 437' font + + display.setCursor(0, 0); + display.write("ETH MAC:"); + display.setCursor(25, 8); + display.print(ETH.macAddress()); + display.setCursor(0, 16); + display.print("IPv4:"); + display.setCursor(25, 24); + display.print(ETH.localIP()); + + display.display(); + delay(5000); // Pause for 5 seconds +} void test_screen() { display.clearDisplay(); - display.setTextSize(1); // Normal 1:1 pixel scale + display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); - display.cp437(true); // Use full 256 char 'Code Page 437' font + display.cp437(true); // Use full 256 char 'Code Page 437' font display.write("CHECKER"); display.display(); display.startscrollright(0x00, 0x07); @@ -259,86 +322,97 @@ void test_screen() { display.stopscroll(); } -void show_CH() { +void show_CH(String unit) { display.clearDisplay(); - - display.setTextSize(2); // Normal 1:1 pixel scale + + display.setTextSize(2); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text - display.cp437(true); // Use full 256 char 'Code Page 437' font + display.cp437(true); // Use full 256 char 'Code Page 437' font display.setCursor(0, 0); display.write("CH1"); - display.setCursor(SCREEN_WIDTH*5/8, 0); + display.setCursor(SCREEN_WIDTH * 5 / 8, 0); display.write("CH3"); - display.setCursor(0, SCREEN_HEIGHT/2); + display.setCursor(0, SCREEN_HEIGHT / 2); display.write("CH2"); - display.setCursor(SCREEN_WIDTH*5/8, SCREEN_HEIGHT/2); + display.setCursor(SCREEN_WIDTH * 5 / 8, SCREEN_HEIGHT / 2); display.write("CH4"); - display.setCursor(SCREEN_WIDTH*10/28, SCREEN_HEIGHT*1/4); - display.write("mV"); - delay(500); + display.setTextSize(1); + if (unit.length() == 4) { + display.setCursor(SCREEN_WIDTH * 10 / 28, SCREEN_HEIGHT * 2 / 5); + } else if (unit.length() == 2) { + display.setCursor(SCREEN_WIDTH * 11 / 28, SCREEN_HEIGHT * 2 / 5); + } + display.print(unit); + delay(1000); display.display(); - } -void show_VAL(int dadc0, int dadc1, int dadc2, int dadc3) { +void show_VAL(int dadc0, int dadc1, int dadc2, int dadc3, String unit) { display.clearDisplay(); - - display.setTextSize(2); // Normal 1:1 pixel scale + + display.setTextSize(2); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text - display.cp437(true); // Use full 256 char 'Code Page 437' font + display.cp437(true); // Use full 256 char 'Code Page 437' font display.setCursor(0, 0); display.print(dadc0); - display.setCursor(SCREEN_WIDTH*5/8, 0); + display.setCursor(SCREEN_WIDTH * 5 / 8, 0); display.print(dadc2); - display.setCursor(0, SCREEN_HEIGHT/2 ); + display.setCursor(0, SCREEN_HEIGHT / 2); display.print(dadc1); - display.setCursor(SCREEN_WIDTH*5/8, SCREEN_HEIGHT/2 ); + display.setCursor(SCREEN_WIDTH * 5 / 8, SCREEN_HEIGHT / 2); display.print(dadc3); - display.setCursor(SCREEN_WIDTH*10/28, SCREEN_HEIGHT*1/4); - display.write("mV"); - delay(1000); + display.setTextSize(1); + if (unit.length() == 4) { + display.setCursor(SCREEN_WIDTH * 10 / 28, SCREEN_HEIGHT * 2 / 5); + } else if (unit.length() == 2) { + display.setCursor(SCREEN_WIDTH * 11 / 28, SCREEN_HEIGHT * 2 / 5); + } + display.print(unit); + delay(1); display.display(); - } -void loop(){ -//for Telnet Server Connection +void loop() { + // for Telnet Server Connection uint8_t i; if (eth_connected == true) { - //check if there are any new clients + // check if there are any new clients if (server.hasClient()) { - for(i = 0; i < MAX_SRV_CLIENTS; i++) { - //find free/disconnected spot + for (i = 0; i < MAX_SRV_CLIENTS; i++) { + // find free/disconnected spot if (!serverClients[i] || !serverClients[i].connected()) { - if(serverClients[i]) serverClients[i].stop(); + if (serverClients[i]) + serverClients[i].stop(); serverClients[i] = server.available(); - if (!serverClients[i]) Serial.println("available broken"); + if (!serverClients[i]) + Serial.println("available broken"); Serial.print("\nNew client: "); - Serial.print(i); Serial.print(' '); + Serial.print(i); + Serial.print(' '); Serial.println(serverClients[i].remoteIP()); break; } } if (i >= MAX_SRV_CLIENTS) { - //no free/disconnected spot so reject + // no free/disconnected spot so reject server.available().stop(); } } - //check clients for data + // check clients for data String getstring; - for(i = 0; i < MAX_SRV_CLIENTS; i++) { + for (i = 0; i < MAX_SRV_CLIENTS; i++) { if (serverClients[i] && serverClients[i].connected()) { - if(serverClients[i].available()) { - //get data from the telnet client and push it to I2C - while(serverClients[i].available()) {getstring = char(serverClients[i].read()); - for(uint8_t m=0; m < getstring.length(); m++){ + if (serverClients[i].available()) { + // get data from the telnet client and push it to I2C + while (serverClients[i].available()) { + getstring = char(serverClients[i].read()); + for (uint8_t m = 0; m < getstring.length(); m++) { getdata(getstring.charAt(m)); } } } - } - else { + } else { if (serverClients[i]) { serverClients[i].stop(); } @@ -346,29 +420,58 @@ void loop(){ } } - get_adc_val(); //get the actual measured values from adc - - delay(1000); + get_adc_val(); // get the actual measured values from adc + + delay(100); +} + +void set_offset(int16_t new_offset_val, int chan_offset_num) { + if (chan_offset_num == 0) { + offset0 = new_offset_val; + } else if (chan_offset_num == 1) { + offset1 = new_offset_val; + } else if (chan_offset_num == 2) { + offset2 = new_offset_val; + } else if (chan_offset_num == 3) { + offset3 = new_offset_val; + } else if (chan_offset_num == 5) { + offset0 = new_offset_val; + offset1 = new_offset_val; + offset2 = new_offset_val; + offset3 = new_offset_val; } +} + +void set_voltage_divider_factor(float new_vol_div_fac) { + vol_div_fac = new_vol_div_fac/1000.0; +} + +void set_device_transformation_factor(float new_dev_trans_fac) { + dev_trans_fac = new_dev_trans_fac/1000.0; +} + +void set_unit(uint8_t new_unit) { + unit = possible_units[new_unit]; +} void set_adc_gain(uint8_t new_gain) { - //Set the ADC Gain parameter and choose the right conversion factor - ads.setGain(asetGAIN[new_gain]); + // Set the ADC Gain parameter and choose the right conversion factor + ads.setGain(asetGAIN[new_gain]); setADCconversion = acGAIN[new_gain]; - } +} void get_adc_val() { - //Get the actual ADC measurment values in dimension of mV + // Get the actual ADC measurment values in dimension of mV adc0 = ads.readADC_SingleEnded(0); adc1 = ads.readADC_SingleEnded(1); adc2 = ads.readADC_SingleEnded(2); adc3 = ads.readADC_SingleEnded(3); - fadc0 = adc0 * setADCconversion; - fadc1 = adc1 * setADCconversion; - fadc2 = adc2 * setADCconversion; - fadc3 = adc3 * setADCconversion; + fadc0 = adc0 * setADCconversion * vol_div_fac * dev_trans_fac + offset0; + fadc1 = adc1 * setADCconversion * vol_div_fac * dev_trans_fac + offset1; + fadc2 = adc2 * setADCconversion * vol_div_fac * dev_trans_fac + offset2; + fadc3 = adc3 * setADCconversion * vol_div_fac * dev_trans_fac + offset3; String sadc0 = String(fadc0); String sadc1 = String(fadc1); @@ -376,172 +479,254 @@ void get_adc_val() { String sadc3 = String(fadc3); int dadc0 = fadc0; - int dadc1 = fadc1; + int dadc1 = fadc1; int dadc2 = fadc2; int dadc3 = fadc3; - - String sbuf = String("\nAIN0: " + sadc0 + "mV\n" + "AIN1: " + sadc1 + "mV\n" + "AIN2: " + sadc2 + "mV\n" + "AIN3: " + sadc3 + "mV\n "); + + //String unit = possible_units[new_unit]; + String sbuf = String("\nAIN0: " + sadc0 + ' ' + unit + "\n" + "AIN1: " + sadc1 + ' ' + unit + "\n" + "AIN2: " + sadc2 + ' ' + unit + "\n" + "AIN3: " + sadc3 + ' ' + unit + "\n "); Serial.print(sbuf); // for serial output - + size_t len = sbuf.length(); uint8_t buf[len]; - sbuf.toCharArray((char*)buf, len); // Copies the String’s characters to the supplied buffer. + sbuf.toCharArray((char *)buf, len); // Copies the String’s characters to the supplied buffer. counter += 1; - if (counter == 1) { - show_CH(); - } - else if (counter == 4) { - counter = 0; - } - else { - show_VAL(dadc0, dadc1, dadc2, dadc3); - } + if (counter == 1) { + if (eth_connected == true) { + if (show_connection == true) { + connection_screen(); + show_connection = false; + } + } + show_CH(unit); + } else if (counter == 100) { + counter = 0; + } else { + show_VAL(dadc0, dadc1, dadc2, dadc3, unit); + } + + if (eth_connected == false) { + show_connection = true; + } - send_answer_buf(buf, len); //for telnet output + send_answer_buf(buf, len); // for telnet continous output } uint8_t nib_to_hex(uint16_t in, uint8_t nib) { - uint8_t t = (in >> (nib*4)) & 0xF; - if (t <= 9) {return t + 0x30;} - return t - 10 + 0x61; - } - -uint8_t hex_to_int(uint8_t h) { //assumes valid number - if (h < 0x40) return h-0x30; - if (h < 0x50) return h-0x41+10; - return h-0x61+10; + uint8_t t = (in >> (nib * 4)) & 0xF; + if (t <= 9) { + return t + 0x30; } + return t - 10 + 0x61; +} + +uint8_t hex_to_int(uint8_t h) { // assumes valid number + if (h < 0x40) + return h - 0x30; + if (h < 0x50) + return h - 0x41 + 10; + return h - 0x61 + 10; +} -void sub1(uint8_t* c1, uint8_t* c2) { - uint8_t b = hex_to_int(*c1)*16 + hex_to_int(*c2); +void sub1(uint8_t *c1, uint8_t *c2) { + uint8_t b = hex_to_int(*c1) * 16 + hex_to_int(*c2); b -= 1; - *c1 = nib_to_hex(b,1); - *c2 = nib_to_hex(b,0); - } + *c1 = nib_to_hex(b, 1); + *c2 = nib_to_hex(b, 0); +} -void send_answer_buf(uint8_t* buf, size_t len) { +void send_answer_buf(uint8_t *buf, size_t len) { uint8_t i; - for(i = 0; i < MAX_SRV_CLIENTS; i++) { + for (i = 0; i < MAX_SRV_CLIENTS; i++) { if (serverClients[i] && serverClients[i].connected()) { serverClients[i].write(buf, len); delay(1); - } } } +} -void send_answer_hex(uint8_t* rxbuf, uint16_t v) { - txbuf[0]='A'; - txbuf[1]=rxbuf[1]; - txbuf[2]=rxbuf[2]; - txbuf[3]=rxbuf[3];//Switch deactivated - txbuf[4]=rxbuf[4]; - txbuf[5]=rxbuf[5]; - txbuf[6]=nib_to_hex(v,3); - txbuf[7]=nib_to_hex(v,2); - txbuf[8]=nib_to_hex(v,1); - txbuf[9]=nib_to_hex(v,0); - txbuf[10]='\n'; +void send_answer_hex(uint8_t *rxbuf, uint16_t v) { + txbuf[0] = 'A'; + txbuf[1] = rxbuf[1]; + txbuf[2] = rxbuf[2]; + txbuf[3] = rxbuf[3]; // Switch deactivated + txbuf[4] = rxbuf[4]; + txbuf[5] = rxbuf[5]; + txbuf[6] = nib_to_hex(v, 3); + txbuf[7] = nib_to_hex(v, 2); + txbuf[8] = nib_to_hex(v, 1); + txbuf[9] = nib_to_hex(v, 0); + txbuf[10] = '\n'; txbuf[11] = 0; size_t len = 12; send_answer_buf(txbuf, len); - } +} void forward_msg(uint8_t i) { - sub1(&rxbuf[1],&rxbuf[2]); - memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,i); + sub1(&rxbuf[1], &rxbuf[2]); + memcpy((uint8_t *)txbuf, (uint8_t *)rxbuf, i); txbuf[i] = 0; -// send_answer_buf(txbuf); - } - + // send_answer_buf(txbuf); +} + uint8_t is_my_address(uint8_t s) { if (ISMYADDR()) { - //rxbuf[2] -= '0'; // write number to buffer, instead of ascii. + // rxbuf[2] -= '0'; // write number to buffer, instead of ascii. return 1; } else { forward_msg(s); return 0; } } - + void getdata(uint8_t buf) { // get data by register mode if (rxcnt != 0 || (buf == 'A' || buf == 'W' || buf == 'R')) { rxbuf[rxcnt++] = buf; } - if (buf == '\n' || buf == '\r') { //End of Command + if (rxcnt != 0 & buf == '\n' || buf == '\r') { // End of Command -//answer + // answer if (rxbuf[0] == 'A') { - - memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,10); - txbuf[11] = 0; - size_t len = 12; - send_answer_buf(txbuf, len); + memcpy((uint8_t *)txbuf, (uint8_t *)rxbuf, 10); + txbuf[11] = 0; + size_t len = 12; + send_answer_buf(txbuf, len); } else if (rxbuf[0] == 'S') { // Scann of chain, returns number of boards - txbuf[0] = 'S'; - uint8_t length = rxcnt - 2 ; // Length of Counter - //read current counter value - uint32_t cnt = 0; - if (length == 0){ - length = 1; - } else { - uint32_t base = 1; - for (uint8_t i = length; i > 0; i--){ - cnt += hex_to_int(rxbuf[i])*base; - base *= 16; - } + + txbuf[0] = 'S'; + uint8_t length = rxcnt - 2; // Length of Counter + // read current counter value + uint32_t cnt = 0; + if (length == 0) { + length = 1; + } else { + uint32_t base = 1; + for (uint8_t i = length; i > 0; i--) { + cnt += hex_to_int(rxbuf[i]) * base; + base *= 16; + } + } + // inc counter value + cnt++; + // send to next uC + if ((cnt % 16) == 0) + length++; + for (uint8_t i = length; i > 0; i--) { + txbuf[i] = nib_to_hex(cnt, length - i); + } + if (length > 8) + length = 8; // skip to keep a clean ending of message + txbuf[length + 1] = 10; + txbuf[length + 2] = 0; + send_answer_buf(txbuf, length); + rxcnt = 0; + } else if (is_my_address(10)) { // message is for this uC + + // write + if (rxbuf[0] == 'W') { + // ADCsettings + if (hex_to_int(rxbuf[5]) == 9) { + // uint8_t val = + // (hex_to_int(rxbuf[7])*16+hex_to_int(rxbuf[8]))&0xFF; + new_gain = (hex_to_int(rxbuf[9])); + set_adc_gain(new_gain); + + send_answer_hex(&rxbuf[0], new_gain); + } + if (hex_to_int(rxbuf[5]) == 11) { + //units + if (hex_to_int(rxbuf[4]) == 0) { + new_unit = (hex_to_int(rxbuf[9])); + set_unit(new_unit); + + send_answer_hex(&rxbuf[0], new_unit); } - // inc counter value - cnt++; - //send to next uC - if ((cnt % 16) == 0) length++; - for (uint8_t i = length; i > 0; i--){ - txbuf[i] = nib_to_hex(cnt,length-i); + + //transformationfactor + if (hex_to_int(rxbuf[4]) == 1) { + new_dev_trans_fac = (hex_to_int(rxbuf[6]) * 4096 + hex_to_int(rxbuf[7]) * 256 + hex_to_int(rxbuf[8]) * 16 + hex_to_int(rxbuf[9])); + set_device_transformation_factor(new_dev_trans_fac); + + send_answer_hex(&rxbuf[0], new_dev_trans_fac); } - if (length > 8) length = 8; // skip to keep a clean ending of message - txbuf[length+1] = 10; - txbuf[length+2] = 0; - send_answer_buf(txbuf, length); - rxcnt = 0; - } else if (is_my_address(10)){ // message is for this uC - -//write - if (rxbuf[0] == 'W'){ - //ADCsettings - if (hex_to_int(rxbuf[5]) == 9) { -// uint8_t val = (hex_to_int(rxbuf[7])*16+hex_to_int(rxbuf[8]))&0xFF; - new_gain = (hex_to_int(rxbuf[7])*16+hex_to_int(rxbuf[8]))&0xFF; - - set_adc_gain(new_gain); - - send_answer_hex(&rxbuf[0], new_gain); - } - } + + //input Voltage Divider + if (hex_to_int(rxbuf[4]) == 2) { + new_vol_div_fac = (hex_to_int(rxbuf[6]) * 4096 + hex_to_int(rxbuf[7]) * 256 + hex_to_int(rxbuf[8]) * 16 + hex_to_int(rxbuf[9])); + set_voltage_divider_factor(new_vol_div_fac); -//read - if (rxbuf[0] == 'R'){ - //read single ADC Channel - if (hex_to_int(rxbuf[5]) == 10) { - uint16_t adc_val = 0xFFFF; - //CH0 - if (hex_to_int(rxbuf[4]) == 0) {adc_val=fadc0*16; + send_answer_hex(&rxbuf[0], new_vol_div_fac); + } } - //CH1 - if (hex_to_int(rxbuf[4]) == 1) {adc_val=fadc1*16; + if (hex_to_int(rxbuf[5]) == 12) { + //offset + new_offset_val = (hex_to_int(rxbuf[6]) * 4096 + hex_to_int(rxbuf[7]) * 256 + hex_to_int(rxbuf[8]) * 16 + hex_to_int(rxbuf[9])); + chan_offset_num = (hex_to_int(rxbuf[4])); + set_offset(new_offset_val, chan_offset_num); + + send_answer_hex(&rxbuf[0], new_offset_val); + } + } + + // read + if (rxbuf[0] == 'R'){ + // read single ADC Channel + if (hex_to_int(rxbuf[5]) == 10) { + uint16_t adc_val = 0xFFFF; + // CH0 + if (hex_to_int(rxbuf[4]) == 0) { + adc_val = fadc0 * 16; + } + // CH1 + if (hex_to_int(rxbuf[4]) == 1) { + adc_val = fadc1 * 16; + } + // CH2 + if (hex_to_int(rxbuf[4]) == 2) { + adc_val = fadc2 * 16; + } + // CH3 + if (hex_to_int(rxbuf[4]) == 3) { + adc_val = fadc3 * 16; + } + send_answer_hex(&rxbuf[0], adc_val); } - //CH2 - if (hex_to_int(rxbuf[4]) == 2) {adc_val=fadc2*16; + if (hex_to_int(rxbuf[5]) == 11) { + uint16_t device_set = 0xFFFF; + if (hex_to_int(rxbuf[4]) == 1) { + device_set = dev_trans_fac; + } + if (hex_to_int(rxbuf[4]) == 2) { + device_set = vol_div_fac; + } + send_answer_hex(&rxbuf[0], device_set); } - //CH3 - if (hex_to_int(rxbuf[4]) == 3) {adc_val=fadc3*16; + if (hex_to_int(rxbuf[5]) == 12) { + uint16_t device_set = 0xFFFF; + if (hex_to_int(rxbuf[4]) == 0) { + offset_val = offset0; + } + if (hex_to_int(rxbuf[4]) == 1) { + offset_val = offset1; + } + if (hex_to_int(rxbuf[4]) == 2) { + offset_val = offset2; + } + if (hex_to_int(rxbuf[4]) == 3) { + offset_val = offset3; + } + if (hex_to_int(rxbuf[4]) == 5) { + offset_val = offset0; + } + send_answer_hex(&rxbuf[0], offset_val); } - send_answer_hex(&rxbuf[0], adc_val); - } - } + } } - if (rxcnt >= 10 || buf == '\n' || buf == '\r') { rxcnt = 0; } } - } + if (rxcnt >= 10 || buf == '\n' || buf == '\r') { + rxcnt = 0;} +} diff --git a/esp32/EthernetUART/LANTelnetToI2C_Board/live_telnet_data_plot.py b/esp32/EthernetUART/LANTelnetToI2C_Board/live_telnet_data_plot.py new file mode 100644 index 0000000..9f596a8 --- /dev/null +++ b/esp32/EthernetUART/LANTelnetToI2C_Board/live_telnet_data_plot.py @@ -0,0 +1,98 @@ +__author__ = "Artz, Ole" +__email__ = "ole.artz@stud.uni-frankfurt.de" + + +import socket +import sys +import matplotlib.pyplot as plt +import matplotlib.animation as animation + + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +AIN0_list = list() +AIN1_list = list() +AIN2_list = list() +AIN3_list = list() + +unit = str() +plot_title = str() +filename = str(sys.argv[3]) #ADC_ETHERNET_val.txt + + +fig = plt.figure('ADC_Ethernet 4 CH Measurment') +ax1 = fig.add_subplot(1,1,1) + +def connection(): + HOST = str(sys.argv[1]) #192.168.8.63 + PORT = int(sys.argv[2]) #2323 + + s.connect( (HOST,PORT) ) + + +def get_data(): + reader = s.recv(1024).decode() + try: + with open(filename, 'r') as file: + file_history = str(file.read()) + with open(filename, "w") as file: + file.write(file_history + '\n' + str(reader)) + except: + with open(filename, "w") as file: + file.write(str(reader)) + file.close() + + return reader + + +def split_data(reader): + + unit = reader[reader.rfind(' ')+1:reader.rfind('\n')] + + AIN0_list.append(float(reader[reader.find('AIN0: ') + 6:reader.find(unit)-1])) + AIN1_list.append(float(reader[reader.find('AIN1: ') + 6:reader.find(unit, reader.find('AIN1: '))-1])) + AIN2_list.append(float(reader[reader.find('AIN2: ') + 6:reader.find(unit, reader.find('AIN2: '))-1])) + AIN3_list.append(float(reader[reader.find('AIN3: ') + 6:reader.find(unit, reader.find('AIN3: '))-1])) + + return unit + +# check for split data works fine +# print(AIN0_list) +# print(AIN1_list) +# print(AIN2_list) +# print(AIN3_list) + + +def animate(i): + reader = get_data() + unit = split_data(reader) + + ax1.clear() + ax1.plot(AIN0_list, 'r', label="AIN0") + ax1.plot(AIN1_list, 'b', label="AIN1") + ax1.plot(AIN2_list, 'g', label="AIN2") + ax1.plot(AIN3_list, 'y', label="AIN3") + + if unit == 'mV': + plot_title = 'Voltage' + elif unit == 'mA': + plot_title = 'Current' + elif unit == 'mbar': + plot_title = 'Pressure' + elif unit == 'degC': + plot_title = 'Temperature' + + plt.title(plot_title) + plt.xlabel('~0.5s') + plt.ylabel(unit) + plt.legend(loc=2) + + +def main(): + connection() + + ani = animation.FuncAnimation(fig, animate, interval=500) + plt.show() + +if __name__ == '__main__': + main() diff --git a/esp32/EthernetUART/LANTelnetToI2C_Board/quickstart 4CH ADC_Ethernet Portable Board.pdf b/esp32/EthernetUART/LANTelnetToI2C_Board/quickstart 4CH ADC_Ethernet Portable Board.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ec1532d6ded262b771285ab5b43cc3ccf73ec63f GIT binary patch literal 60237 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 z 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