espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.03k stars 7.3k forks source link

HardwareSerial must implement pure virtual Print::write(uint8*) #2045

Closed Bascy closed 4 years ago

Bascy commented 5 years ago

Using Eclipse, an error is shown in HardwareSerial.h stating that it instantiates HardwareSerial objects while Print::write(uint8_t) is not implemented.

Print.h indeed contains a pure virtual definition of write:

virtual size_t write(uint8_t) = 0;

Neither Stream.h nor HardwareSerial.h implement this method.

stickbreaker commented 5 years ago

@Bascy really? What about this? HardwareSerial::write()

Chuck.

Bascy commented 5 years ago

You are right, but It misses the override directive

bertmelis commented 5 years ago

https://stackoverflow.com/questions/13880205/is-the-override-keyword-just-a-check-for-a-overridden-virtual-method

Bascy commented 5 years ago

It seems that only the C++ indexer in Eclipse is complaining about it, it actually does compile

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

kbickham commented 4 years ago

Preface, I'm not the most seasoned in dealing with code handling hardware interfaces, but I'm working on Sr. Design and I have no other option. I believe my case here is relevant. It will compile, but I'm trying to rewrite a library for a display that is type casting to uint8_t as a write. If it was functional on the hardware, I would have slept last night.

line 368 (first place it references in trace) reads : ... deviceSerial->write((uint8_t)GENIE_READ_OBJ); ...

Details first error ================================== 07:34:59.197 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled. 07:34:59.197 -> Core 1 register dump: 07:34:59.197 -> PC : 0x400d1faf PS : 0x00060f30 A0 : 0x800d21bd A1 : 0x3ffb1f40 07:34:59.197 -> A2 : 0x3ffbfea4 A3 : 0x00000001 A4 : 0x00000000 A5 : 0x00000000 07:34:59.197 -> A6 : 0xffffffff A7 : 0x3ffbebe0 A8 : 0x800d1f9e A9 : 0x3ffb1f20 07:34:59.197 -> A10 : 0x00000000 A11 : 0xfa000000 A12 : 0xc1400000 A13 : 0x00000001 07:34:59.231 -> A14 : 0x00060120 A15 : 0x00000000 SAR : 0x0000000a EXCCAUSE: 0x0000001c 07:34:59.231 -> EXCVADDR: 0x00000000 LBEG : 0x4000c349 LEND : 0x4000c36b LCOUNT : 0xffffffff 07:34:59.231 -> 07:34:59.231 -> Backtrace: 0x400d1faf:0x3ffb1f40 0x400d21ba:0x3ffb1f60 0x400d1a81:0x3ffb1f90 0x400d4a49:0x3ffb1fb0 0x4008543d:0x3ffb1fd0 07:34:59.264 -> 07:34:59.264 -> Rebooting... 07:34:59.264 -> ets Jun 8 2016 00:22:57 07:34:59.264 -> 07:34:59.264 -> rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) 07:34:59.264 -> configsip: 0, SPIWP:0xee 07:34:59.264 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 07:34:59.264 -> mode:DIO, clock div:1 07:34:59.264 -> load:0x3fff0018,len:4 07:34:59.264 -> load:0x3fff001c,len:1100 07:34:59.264 -> load:0x40078000,len:9232 07:34:59.264 -> load:0x40080400,len:6400 07:34:59.264 -> entry 0x400806a8 ======================================================= 0x400d1faf: Genie::autoPinger() at C:\Users\Lauren\Downloads\arduino-nightly\libraries\genieArduino\src\genieArduino.cpp line 368 0x400d21ba: Genie::DoEvents() at C:\Users\Lauren\Downloads\arduino-nightly\libraries\genieArduino\src\genieArduino.cpp line 416 0x400d1a81: loop() at C:\Port2ESPhdc\prelimAVRport1/prelimAVRport1.ino line 249 0x400d4a49: loopTask(void*) at C:\Users\Lauren\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.2\cores\esp32\main.cpp line 19 0x4008543d: vPortTaskWrapper at /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/port.c line 143
stickbreaker commented 4 years ago

@kbickham

07:34:59.197 -> Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.

is telling you that a memory storage location was referenced that is inaccessible.

Usually it means a pointer has a null value.

What is GENIE_READ_OBJ? You are telling the compiler to treat it as a single byte.

Please post enough code to show your declaration, and the current value stored in it.

Memory map from page 25 of the ESP32 Technical reference manual V4.0 esp32_memory

Only addresses in these range are valid to access. basically 0x3ffb0000 to 0x400c1FFF and 0x50000000 to 0x50001fff.

Chuck.

kbickham commented 4 years ago

Well I feel a little dumb. I'm not that experienced, but I'm learning... I genuinely thank you for the response. The genie library is basically a uart protocol for commands to the display. I've invested so much into the interface design that I'm tied to it c. It sends/receives data in 8 bit chunks, wasn't my design. I've seen some ported libraries handling everything in 2 byte chunks (I actually can't find where they shift anything before output, as I don't think they're spending half their bandwidth transmitting zeros?).

The READOBJECT returns a couple bytes each for object id, index... the exact values in base 10 are. I realize this may not be related not the issue now, but I see it worthy of adequately responding to your question:

define GENIE_OBJ_DIPSW 0

define GENIE_OBJ_KNOB 1

define GENIE_OBJ_ROCKERSW 2

define GENIE_OBJ_ROTARYSW 3

define GENIE_OBJ_SLIDER 4

define GENIE_OBJ_TRACKBAR 5

define GENIE_OBJ_WINBUTTON 6

define GENIE_OBJ_ANGULAR_METER 7

define GENIE_OBJ_COOL_GAUGE 8

define GENIE_OBJ_CUSTOM_DIGITS 9

define GENIE_OBJ_FORM 10

define GENIE_OBJ_GAUGE 11

define GENIE_OBJ_IMAGE 12

define GENIE_OBJ_KEYBOARD 13

define GENIE_OBJ_LED 14

define GENIE_OBJ_LED_DIGITS 15

define GENIE_OBJ_METER 16

define GENIE_OBJ_STRINGS 17

define GENIE_OBJ_THERMOMETER 18

define GENIE_OBJ_USER_LED 19

define GENIE_OBJ_VIDEO 20

define GENIE_OBJ_STATIC_TEXT 21

define GENIE_OBJ_SOUND 22

define GENIE_OBJ_TIMER 23

define GENIE_OBJ_SPECTRUM 24

define GENIE_OBJ_SCOPE 25

define GENIE_OBJ_TANK 26

define GENIE_OBJ_USERIMAGES 27

define GENIE_OBJ_PINOUTPUT 28

define GENIE_OBJ_PININPUT 29

define GENIE_OBJ_4DBUTTON 30

define GENIE_OBJ_ANIBUTTON 31

define GENIE_OBJ_COLORPICKER 32

define GENIE_OBJ_USERBUTTON 33

// reserved for magic functions 34

define GENIE_OBJ_ISMARTGAUGE 35

define GENIE_OBJ_ISMARTSLIDER 36

define GENIE_OBJ_ISMARTKNOB 37

Details ' /********************************************************************* * This file is part of genieArduino: * genieArduino is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * genieArduino is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with genieArduino. * If not, see . *********************************************************************/ #if defined (SPARK) #include "application.h" #define lowByte(w) ((uint8_t)((w) & 0xFF)) #define highByte(w) ((uint8_t)((w) >> 8)) #else #if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif #endif #include "genieArduino.h" #include #include #define DEC 10 #define HEX 16 #define OCT 8 #define BIN 2 // ###################################### // ## GENIE CLASS ####################### // ###################################### Genie::Genie() { UserHandler = NULL; UserByteReader = NULL; UserDoubleByteReader = NULL; debugSerial = NULL; } // ###################################### // ## Attach Event Handler ############## // ###################################### void Genie::AttachEventHandler (UserEventHandlerPtr handler) { UserHandler = handler; uint8_t rx_data[6]; // display status already collected from Begin function, user just enabled handler, so give a status. if ( displayDetected ) { rx_data[0] = GENIE_PING; rx_data[1] = GENIE_READY; rx_data[2] = 0; rx_data[3] = 0; rx_data[4] = 0; rx_data[5] = 0; EnqueueEvent(rx_data); // send ready state to user handler. } else { rx_data[0] = GENIE_PING; rx_data[1] = GENIE_DISCONNECTED; rx_data[2] = 0; rx_data[3] = 0; rx_data[4] = 0; rx_data[5] = 0; EnqueueEvent(rx_data); } } // ###################################### // ## Attach Magic Byte Reader ########## // ###################################### void Genie::AttachMagicByteReader(UserBytePtr handler) { UserByteReader = handler; } // ###################################### // ## Attach Magic Double Byte Reader ### // ###################################### void Genie::AttachMagicDoubleByteReader(UserDoubleBytePtr handler) { UserDoubleByteReader = handler; } // ###################################### // ## Genie Uptime Request ############## // ###################################### uint32_t Genie::uptime() { if ( displayDetected ) return millis() - display_uptime; else return 0; } // ###################################### // ## GetNextByte ####################### // ###################################### uint8_t Genie::GetNextByte() { if ( !displayDetected ) return -1; // user code may keep requesting, block till ready. uint8_t rx_data[6]; uint32_t timeout = millis(); while (deviceSerial->available() < 1) { delayedCycles = millis(); displayDetectTimer = millis(); if ( millis() - timeout >= 2000 ) { // we issue an immediate manual disconnect. displayDetectTimer = millis(); displayDetected = 0; while ( deviceSerial->available() > 0 ) deviceSerial->read(); if ( debugSerial != NULL ) { debugSerial->println(F("*** Genie Disconnected from GetNextByte! ***")); } rx_data[0] = GENIE_PING; rx_data[1] = GENIE_DISCONNECTED; rx_data[2] = 0; rx_data[3] = 0; rx_data[4] = 0; rx_data[5] = 0; EnqueueEvent(rx_data); return -1; } continue; } delayedCycles = millis(); displayDetectTimer = millis(); return deviceSerial->read(); } // ###################################### // ## GetNextDoubleByte ################# // ###################################### uint16_t Genie::GetNextDoubleByte() { if ( !displayDetected ) return -1; // user code may keep requesting, block till ready. uint8_t rx_data[6]; uint16_t out; uint32_t timeout = millis(); while (deviceSerial->available() < 2) { delayedCycles = millis(); displayDetectTimer = millis(); if ( millis() - timeout >= 2000 ) { // we issue an immediate manual disconnect. displayDetectTimer = millis(); displayDetected = 0; while ( deviceSerial->available() > 0 ) deviceSerial->read(); if ( debugSerial != NULL ) { debugSerial->println(F("*** Genie Disconnected from GetNextByte! ***")); } rx_data[0] = GENIE_PING; rx_data[1] = GENIE_DISCONNECTED; rx_data[2] = 0; rx_data[3] = 0; rx_data[4] = 0; rx_data[5] = 0; EnqueueEvent(rx_data); return -1; } continue; } delayedCycles = millis(); displayDetectTimer = millis(); out = (deviceSerial->read()) << 8; out |= deviceSerial->read(); return out; } // ###################################### // ## Setup ############################# // ###################################### bool Genie::Begin(Stream &serial) { deviceSerial = &serial; display_uptime = millis(); // start uptime timer (ms) genieStart = 1; // start form request on startup ReadObject(GENIE_OBJ_FORM, (uint8_t)0x00); // send form request uint32_t timeout_start = millis(); // timeout timer while ( millis() - timeout_start <= 250 ) { // blocking loop, releases after 150ms to timeout, or sooner if display's detected. if ( DoEvents() == GENIE_REPORT_OBJ && !genieStart ) return 1; // form is updated. } displayDetected = 0; return 0; // timeout occured, status offline. } // ###################################### // ## Debug ############################# // ###################################### void Genie::debug(Stream &serial, uint8_t level) { debugSerial = &serial; debug_level = level; } // ###################################### // ## Timeout ########################### // ###################################### uint8_t Genie::timeout(uint16_t value) { if ( value < 50 ) return 0; // no less than 50 recommended! this will trigger the disconnect flag! GENIE_CMD_TIMEOUT = value; return 1; } // ###################################### // ## Online Status ##################### // ###################################### bool Genie::online() { return displayDetected; } // ###################################### // ## Online and Active Form ############ // ###################################### bool Genie::online(uint8_t activeForm) { if ( displayDetected && currentForm == activeForm ) return 1; return 0; } // ###################################### // ## Current Form ###################### // ###################################### uint8_t Genie::form() { return currentForm; } // ###################################### // ## Change Form ####################### // ###################################### void Genie::form(uint8_t newForm) { WriteObject(GENIE_OBJ_FORM, newForm, (uint8_t)0x00); } // ###################################### // ## Recovery Pulses ################### // ###################################### void Genie::recover(uint8_t pulses) { recover_pulse = pulses; } // ###################################### // ## Get Event Data #################### // ###################################### uint16_t Genie::GetEventData (genieFrame * e) { return (e->reportObject.data_msb << 8) + e->reportObject.data_lsb; } // ###################################### // ## Event Is ########################## // ###################################### uint8_t Genie::EventIs(genieFrame * e, uint8_t cmd, uint8_t object, uint8_t index) { return (e->reportObject.cmd == cmd && e->reportObject.object == object && e->reportObject.index == index); } // ###################################### // ## Read Object ####################### // ###################################### uint8_t Genie::ReadObject(uint8_t object, uint8_t index) { if ( !displayDetected ) return -1; uint8_t checksum; deviceSerial->write((uint8_t)GENIE_READ_OBJ); checksum = GENIE_READ_OBJ; deviceSerial->write(object); checksum ^= object; deviceSerial->write(index); checksum ^= index; deviceSerial->write(checksum); return 0; } // ###################################### // ## Write Object ###################### // ###################################### uint8_t Genie::WriteObject(uint8_t object, uint8_t index, uint16_t data) { if ( !displayDetected ) return -1; uint8_t checksum; pendingACK = 1; deviceSerial->write(GENIE_WRITE_OBJ); checksum = GENIE_WRITE_OBJ; deviceSerial->write(object); checksum ^= object; deviceSerial->write(index); checksum ^= index; deviceSerial->write(highByte(data)); checksum ^= highByte(data); deviceSerial->write(lowByte(data)); checksum ^= lowByte(data); deviceSerial->write(checksum); uint32_t timeout_write = millis(); while ( millis() - timeout_write <= GENIE_CMD_TIMEOUT ) { uint8_t command_return = DoEvents(); if ( command_return == GENIE_ACK ) { if ( ( debug_level == 6 || debug_level == 1 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteObject *** --->")); debugSerial->print(object); debugSerial->println(F("... ACK !")); } return 1; } if ( command_return == GENIE_NAK ) { if ( ( debug_level == 6 || debug_level == 1 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteObject *** --->")); debugSerial->print(object); debugSerial->println(F("... NAK !")); } return 0; } } displayDetectTimer = millis() + DISPLAY_TIMEOUT + 10000; //manual disconnect if ( ( debug_level == 6 || debug_level == 1 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteObject *** --->")); debugSerial->print(object); debugSerial->println(F("... Timeout!")); } return -1; // timeout } // ###################################### // ## Write Contrast #################### // ###################################### uint8_t Genie::WriteContrast(uint8_t value) { if ( !displayDetected ) return -1; uint8_t checksum; pendingACK = 1; deviceSerial->write(GENIE_WRITE_CONTRAST); checksum = GENIE_WRITE_CONTRAST; deviceSerial->write(value); checksum ^= value; deviceSerial->write(checksum); uint32_t timeout_write = millis(); while ( millis() - timeout_write <= GENIE_CMD_TIMEOUT ) { uint8_t command_return = DoEvents(); if ( command_return == GENIE_ACK ) { if ( ( debug_level == 6 || debug_level == 1 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie Contrast *** --->")); debugSerial->println(F("... ACK !")); } return 1; } if ( command_return == GENIE_NAK ) { if ( ( debug_level == 6 || debug_level == 1 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie Contrast *** --->")); debugSerial->println(F("... NAK !")); } return 0; } } displayDetectTimer = millis() + DISPLAY_TIMEOUT + 10000; //manual disconnect if ( ( debug_level == 6 || debug_level == 1 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie Contrast *** --->")); debugSerial->println(F("... Timeout!")); } return -1; // timeout } // ###################################### // ## Auto Pinger ####################### // ###################################### uint8_t Genie::autoPinger() { uint16_t geniePingTimerChanger; if ( displayDetected ) geniePingTimerChanger = AUTO_PING_CYCLE; // preset online pinger if ( !displayDetected ) geniePingTimerChanger = recover_pulse; // 50ms offline pinger if ( millis() - autoPingTimer > geniePingTimerChanger ) { autoPingTimer = millis(); autoPing = 1; uint8_t checksum; deviceSerial->write((uint8_t)GENIE_READ_OBJ); checksum = GENIE_READ_OBJ; deviceSerial->write((uint8_t)GENIE_OBJ_FORM); checksum ^= (uint8_t)GENIE_OBJ_FORM; deviceSerial->write((uint8_t)0x00); checksum ^= (uint8_t)0x00; deviceSerial->write(checksum); } return 1; } // ###################################### // ## User Ping ######################### // ###################################### uint16_t Genie::Ping(uint16_t interval) { if ( displayDetected ) { if ( millis() - ping_spacer < interval ) return 0; ping_spacer = millis(); pingRequest = 1; uint8_t checksum; deviceSerial->write((uint8_t)GENIE_READ_OBJ); checksum = GENIE_READ_OBJ; deviceSerial->write((uint8_t)GENIE_OBJ_FORM); checksum ^= (uint8_t)GENIE_OBJ_FORM; deviceSerial->write((uint8_t)0x00); checksum ^= (uint8_t)0x00; deviceSerial->write(checksum); return 1; } if ( !displayDetected ) { if ( millis() - ping_spacer > interval ) { ping_spacer = millis(); uint8_t rx_data[6]; rx_data[0] = GENIE_PING; rx_data[1] = GENIE_NAK; rx_data[2] = 0; rx_data[3] = 0; rx_data[4] = 0; rx_data[5] = 0; EnqueueEvent(rx_data); } } return 0; } // ###################################### // ## Do Events ######################### // ###################################### uint8_t Genie::DoEvents() { autoPinger(); // used to keep lcd connection alive uint8_t rx_data[6]; // array for receiving command, payload, and crc. uint8_t checksumVerify; // used to calculate a matching (or not) checksum. // ###################################### // ## SLOW USER CODE? NO PROBLEM! ####### // ###################################### if ( millis() - delayedCycles >= DISPLAY_TIMEOUT ) { displayDetectTimer = millis(); // reset counter to prevent false disconnections. if ( debugSerial != NULL ) debugSerial->println(F("*** Genie Took too long to re-enter DoEvents(), reduce delays in code, self-protection enabled. ***")); } delayedCycles = millis(); // reset the doevents function timeout, every cycle. if ( online() ) { if ( millis() - displayDetectTimer > DISPLAY_TIMEOUT ) { // code online, but lcd is not? displayDetectTimer = millis(); displayDetected = 0; pingRequest = 0; if ( debugSerial != NULL ) { debugSerial->println(F("*** Genie Disconnected from DoEvents! ***")); } rx_data[0] = GENIE_PING; rx_data[1] = GENIE_DISCONNECTED; rx_data[2] = 0; rx_data[3] = 0; rx_data[4] = 0; rx_data[5] = 0; EnqueueEvent(rx_data); currentForm = -1; // reset form holder return -1; } } if ( !displayDetected ) { // not online? pendingACK = 0; // reset pending ACK check currentForm = -1; // reset form holder display_uptime = 0; // keeps timer reset } // ###################################### // ## Main State Machine ################ // ###################################### if ( deviceSerial->available() > 0 ) { uint8_t b = deviceSerial->peek(); // Look at the next byte but don't pull it yet. if ( !displayDetected && ( b == GENIEM_REPORT_BYTES || b == GENIEM_REPORT_DBYTES ) ) b = 0xFF; // force bad bytes instead of false triggering genie magic switches. switch ( b ) { // We're going to parse what we see into the proper switch. case GENIE_ACK: displayDetectTimer = millis(); // reset display timeout since the packet is good. deviceSerial->read(); // remove ACK badByteCounter = 0; // reset the bad byte counter pendingACK = 0; nakInj = 0; // reset NAK counter return GENIE_ACK; case GENIE_NAK: displayDetectTimer = millis(); // reset display timeout since the packet is good. deviceSerial->read(); // remove NAK nakInj++; // increment consecutive NAK counter. while ( deviceSerial->peek() == GENIE_NAK ) deviceSerial->read(); // remove trailing naks for next test if ( nakInj >= 2 ) { // if NAK's are consecutive 2 or more times... nakInj = 0; // reset the counter if ( debugSerial != NULL ) debugSerial->print(F("*** Genie NAK Recovery !!! ***")); deviceSerial->write(0xFF); // inject a byte into the tx buffer to attempt recovery. } pendingACK = 0; return GENIE_NAK; case GENIEM_REPORT_BYTES: if ( deviceSerial->available() < 3 ) break; // magic report event less than 3 bytes? check again. rx_data[0] = deviceSerial->read(); rx_data[1] = deviceSerial->read(); rx_data[2] = deviceSerial->read(); displayDetectTimer = millis(); // reset display timeout since the packet is good. badByteCounter = 0; // reset the bad byte counter if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie Received Magic Bytes *** Index: ")); debugSerial->print(rx_data[1]); debugSerial->print(F(" Length: ")); debugSerial->println(rx_data[2]); } if ( UserByteReader != NULL ) UserByteReader( rx_data[1], rx_data[2] ); else for ( int i = 0; i < rx_data[2]; i++) deviceSerial->read(); (void)GetNextByte(); return GENIEM_REPORT_BYTES; case GENIEM_REPORT_DBYTES: if ( deviceSerial->available() < 3 ) break; // magic report event less than 3 bytes? check again. rx_data[0] = deviceSerial->read(); rx_data[1] = deviceSerial->read(); rx_data[2] = deviceSerial->read(); displayDetectTimer = millis(); // reset display timeout since the packet is good. badByteCounter = 0; // reset the bad byte counter if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie Received Magic Double Bytes *** Index: ")); debugSerial->print(rx_data[1]); debugSerial->print(F(" Length: ")); debugSerial->println(rx_data[2]); } if ( UserDoubleByteReader != NULL ) UserDoubleByteReader( rx_data[1], rx_data[2] ); else for ( int i = 0; i < 2 * rx_data[2]; i++) deviceSerial->read(); (void)GetNextByte(); return GENIEM_REPORT_DBYTES; case GENIE_REPORT_EVENT: if ( deviceSerial->available() < 6 ) break; // report event less than 6 bytes? check again. rx_data[0] = deviceSerial->read(); rx_data[1] = deviceSerial->read(); rx_data[2] = deviceSerial->read(); rx_data[3] = deviceSerial->read(); rx_data[4] = deviceSerial->read(); rx_data[5] = deviceSerial->read(); checksumVerify = rx_data[0]; checksumVerify ^= rx_data[1]; checksumVerify ^= rx_data[2]; checksumVerify ^= rx_data[3]; checksumVerify ^= rx_data[4]; if ( checksumVerify != rx_data[5] ) return 0; //discard this packet, CRC is bad. displayDetectTimer = millis(); // reset display timeout since the packet is good. badByteCounter = 0; // reset the bad byte counter if ( rx_data[1] == GENIE_OBJ_FORM ) currentForm = rx_data[2]; if ( ( debug_level == 6 || debug_level == 2 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie Report Event *** Object: ")); debugSerial->print(rx_data[1]); debugSerial->print(F(" Index: ")); debugSerial->print(rx_data[2]); debugSerial->print(F(" Value: ")); debugSerial->println(256U*rx_data[3]+rx_data[4]); } EnqueueEvent(rx_data); return GENIE_REPORT_EVENT; case GENIE_REPORT_OBJ: if ( deviceSerial->available() < 6 ) break; // report event less than 6 bytes? check again. rx_data[0] = deviceSerial->read(); rx_data[1] = deviceSerial->read(); rx_data[2] = deviceSerial->read(); rx_data[3] = deviceSerial->read(); rx_data[4] = deviceSerial->read(); rx_data[5] = deviceSerial->read(); checksumVerify = rx_data[0]; checksumVerify ^= rx_data[1]; checksumVerify ^= rx_data[2]; checksumVerify ^= rx_data[3]; checksumVerify ^= rx_data[4]; if ( checksumVerify != rx_data[5] ) return 0; //discard this packet, CRC is bad. displayDetectTimer = millis(); // reset display timeout since the packet is good. badByteCounter = 0; // reset the bad byte counter if ( rx_data[1] == GENIE_OBJ_FORM ) currentForm = rx_data[4]; // if ( genieStart ) { genieStart = 0; return GENIE_REPORT_OBJ; } // disable startup form checker if ( ( autoPing || pingRequest ) && rx_data[1] == GENIE_OBJ_FORM ) { if ( autoPing ) { autoPing = 0; //switch off after queueing event if ( !displayDetected ) { // if previously disconnected and now is connected... display_uptime = millis(); // start uptime timer (ms) if ( debugSerial != NULL ) { debugSerial->println(F("*** Genie Connected / Sync! ***")); } rx_data[0] = GENIE_PING; rx_data[1] = GENIE_READY; rx_data[2] = 0; rx_data[3] = 0; rx_data[4] = 0; rx_data[5] = 0; EnqueueEvent(rx_data); // send ready state to user handler. while ( deviceSerial->available() > 0 ) deviceSerial->read(); // clear on new connect displayDetected = 1; // turn on functions } if ( genieStart ) { genieStart = 0; return GENIE_REPORT_OBJ; } break; } if ( pingRequest ) { pingRequest = 0; //switch off after queueing event rx_data[0] = GENIE_PING; rx_data[1] = GENIE_ACK; rx_data[2] = 0; rx_data[3] = 0; rx_data[4] = 0; rx_data[5] = 0; EnqueueEvent(rx_data); // send ACK to user ping request in handler. } break; } if ( ( debug_level == 6 || debug_level == 3 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie Report Object *** Object: ")); debugSerial->print(rx_data[1]); debugSerial->print(F(" Index: ")); debugSerial->print(rx_data[2]); debugSerial->print(F(" Value: ")); debugSerial->println(256U*rx_data[3]+rx_data[4]); } EnqueueEvent(rx_data); return GENIE_REPORT_OBJ; // all other reading of object data flow to event handler default: // unknown bytes found, shift out and start count for possible disconnection. uint8_t bad_byte = deviceSerial->read(); if ( debugSerial != NULL ) { debugSerial->print(F("*** Genie Bad Byte *** ---> 0x")); debugSerial->println(bad_byte,HEX); } badByteCounter++; // We count consecutively to 10 bytes in a row and assume display offline. if ( badByteCounter > 10 ) { badByteCounter = 0; displayDetectTimer = millis() + DISPLAY_TIMEOUT + 10000; } // let DoEvents do the disconnection. return GENIE_NAK; } } if ( !pendingACK && EventQueue.n_events > 0 && UserHandler != NULL ) UserHandler(); // trigger userhandler if queues exist. return 0; } // ###################################### // ## DeQueue Event ##################### // ###################################### uint8_t Genie::DequeueEvent(genieFrame * buff) { if (EventQueue.n_events > 0) { memcpy(buff, &EventQueue.frames[EventQueue.rd_index], GENIE_FRAME_SIZE); EventQueue.rd_index++; EventQueue.rd_index &= MAX_GENIE_EVENTS - 1; EventQueue.n_events--; } return 0; } // ###################################### // ## EnQueue Event ##################### // ###################################### uint8_t Genie::EnqueueEvent (uint8_t * data) { if ( UserHandler == NULL ) { if ( debugSerial != NULL ) debugSerial->println(F("*** Genie Enable AttachEventHandler !!! ***")); return -1; } if (EventQueue.n_events < MAX_GENIE_EVENTS - 2) { int i, j; bool fnd = 0; j = EventQueue.wr_index; for (i = EventQueue.n_events; i > 0; i--) { j--; if (j < 0) j = MAX_GENIE_EVENTS - 1; if ( ( EventQueue.frames[j].reportObject.cmd == data[0] ) && ( EventQueue.frames[j].reportObject.object == data[1] ) && ( EventQueue.frames[j].reportObject.index == data[2] ) ) { EventQueue.frames[j].reportObject.data_msb = data[3]; EventQueue.frames[j].reportObject.data_lsb = data[4]; fnd = 1; break; } } if (!fnd) { memcpy(&EventQueue.frames[EventQueue.wr_index], data, GENIE_FRAME_SIZE); EventQueue.wr_index++; EventQueue.wr_index &= MAX_GENIE_EVENTS - 1; EventQueue.n_events++; } } return 0; } // ###################################### // ## Write Strings ##################### // ###################################### uint8_t Genie::WriteStr(uint8_t index, char *string) { if ( !displayDetected ) return -1; char *p; uint8_t checksum; pendingACK = 1; int len = strlen(string); if (len > 255) return -1; deviceSerial->write(GENIE_WRITE_STR); checksum = GENIE_WRITE_STR; deviceSerial->write(index); checksum ^= index; deviceSerial->write((unsigned char)len); checksum ^= len; for (p = string ; *p ; ++p) { deviceSerial->write(*p); checksum ^= *p; } deviceSerial->write(checksum); uint32_t timeout_write = millis(); while ( millis() - timeout_write <= GENIE_CMD_TIMEOUT ) { uint8_t command_return = DoEvents(); if ( command_return == GENIE_ACK ) return 1; if ( command_return == GENIE_NAK ) return 0; } return -1; // timeout } #ifdef AVR uint8_t Genie::WriteStr(uint8_t index, const __FlashStringHelper *ifsh) { PGM_P p = reinterpret_cast(ifsh); PGM_P p2 = reinterpret_cast(ifsh); size_t n = 0; int len = 0; while (1) { unsigned char d = pgm_read_byte(p2++); len++; if (d == 0) break; } char arr[len]; int x = 0; while (1) { unsigned char c = pgm_read_byte(p++); arr[x] = c; x++; if (c == 0) break; } WriteStr(index, arr); return 0; } #endif uint8_t Genie::WriteStr(uint8_t index, const String &s) { int len = s.length(); char arr[len + 1]; s.toCharArray(arr, len + 1); WriteStr(index, arr); return 0; } uint8_t Genie::WriteStr (uint8_t index, long n) { char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char *str = &buf[sizeof(buf) - 1]; long N = n; n = abs(n); *str = '\0'; do { unsigned long m = n; n /= 10; char c = m - 10 * n; *--str = c < 10 ? c + '0' : c + 'A' - 10; } while (n); if (N < 0) *--str = '-'; WriteStr(index, str); return 0; } uint8_t Genie::WriteStr (uint8_t index, long n, int base) { char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char *str = &buf[sizeof(buf) - 1]; long N; *str = '\0'; if (n >= 0) { // prevent crash if called with base == 1 if (base < 2) base = 10; if (base == 10) { N = n; n = abs(n); } do { unsigned long m = n; n /= base; char c = m - base * n; *--str = c < 10 ? c + '0' : c + 'A' - 10; } while (n); if (base == 10) if (N < 0) *--str = '-'; } else if (n < 0) { unsigned long n2 = (unsigned long)n; uint8_t base2 = base; do { unsigned long m = n2; n2 /= base2; char c = m - base2 * n2; *--str = c < 10 ? c + '0' : c + 'A' - 10; } while (n2); } WriteStr(index, str); return 0; } uint8_t Genie::WriteStr (uint8_t index, int n) { WriteStr (index, (long) n); return 0; } uint8_t Genie::WriteStr (uint8_t index, int n, int base) { WriteStr (index, (long) n, base); return 0; } uint8_t Genie::WriteStr (uint8_t index, unsigned long n) { char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char *str = &buf[sizeof(buf) - 1]; // long N = n; // unused? n = abs(n); *str = '\0'; do { unsigned long m = n; n /= 10; char c = m - 10 * n; *--str = c < 10 ? c + '0' : c + 'A' - 10; } while (n); WriteStr(index, str); return 0; } uint8_t Genie::WriteStr (uint8_t index, unsigned long n, int base) { char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char *str = &buf[sizeof(buf) - 1]; *str = '\0'; // prevent crash if called with base == 1 if (base < 2) base = 10; do { unsigned long m = n; n /= base; char c = m - base * n; *--str = c < 10 ? c + '0' : c + 'A' - 10; } while (n); WriteStr(index, str); return 0; } uint8_t Genie::WriteStr (uint8_t index, unsigned int n) { WriteStr (index, (unsigned long) n); return 0; } uint8_t Genie::WriteStr (uint8_t index, unsigned n, int base) { WriteStr (index, (unsigned long) n, base); return 0; } uint8_t Genie::WriteStr (uint8_t index, double number, int digits) { char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. char *str = &buf[sizeof(buf) - 1]; *str = '\0'; double number2 = number; if (number < 0.0) number = -number; // Round correctly so that print(1.999, 2) prints as "2.00" double rounding = 0.5; for (int i = 0; i < digits; ++i) rounding /= 10.0; number += rounding; unsigned long int_part = (unsigned long)number; double remainder = number - (double)int_part; // Extract digits from the remainder one at a time int digits2 = digits; str = &buf[sizeof(buf) - 1 - digits2]; while (digits2-- > 0) { remainder *= 10.0; int toPrint = int(remainder); char c = toPrint + 48; *str++ = c; remainder -= toPrint; } str = &buf[sizeof(buf) - 1 - digits]; if (digits > 0) *--str = '.'; // Extract the integer part of the number and print it do { unsigned long m = int_part; int_part /= 10; char c = m - 10 * int_part; *--str = c < 10 ? c + '0' : c + 'A' - 10; } while (int_part); // Handle negative numbers if (number2 < 0.0) *--str = '-'; WriteStr(index, str); return 0; } uint8_t Genie::WriteStr (uint8_t index, double n) { WriteStr(index, n, 2); } uint8_t Genie::WriteStrU (uint8_t index, uint16_t *string) { if ( !displayDetected ) return -1; uint16_t *p; uint8_t checksum; int len = 0; p = string; while (*p++) len++; if (len > 255) return -1; deviceSerial->write(GENIE_WRITE_STRU); checksum = GENIE_WRITE_STRU; deviceSerial->write(index); checksum ^= index; deviceSerial->write((unsigned char)(len)); checksum ^= (len); p = string; while (*p) { deviceSerial->write (*p >> 8); checksum ^= *p >> 8; deviceSerial->write (*p); checksum ^= *p++ & 0xff; } deviceSerial->write(checksum); return 1; } // ###################################### // ## Write Magic Bytes ################# // ###################################### uint8_t Genie::WriteMagicBytes (uint8_t index, uint8_t *bytes, uint8_t len, uint8_t report) { if ( UserByteReader == NULL ) { if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) debugSerial->println(F("*** Genie Enable AttachMagicByteReader !!! ***")); return -1; } if ( !displayDetected ) return -1; uint8_t checksum; deviceSerial->write(GENIEM_WRITE_BYTES); checksum = GENIEM_WRITE_BYTES; deviceSerial->write(index); checksum ^= index; deviceSerial->write(len); checksum ^= len; for (int i = 0; i < len; i++) { deviceSerial->write(bytes[i]); checksum ^= bytes[i]; } deviceSerial->write(checksum); uint32_t timeout_write = millis(); if (!report) pendingACK = 1; while ( millis() - timeout_write <= GENIE_CMD_TIMEOUT ) { uint8_t command_return = DoEvents(); if (!report) { if ( command_return == GENIE_ACK ) { if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteMagicBytes *** --->")); debugSerial->print(index); debugSerial->println(F("... ACK !")); } return 1; } if ( command_return == GENIE_NAK ) { if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteMagicBytes *** --->")); debugSerial->print(index); debugSerial->println(F("... NAK !")); } return 0; } } else { if ( command_return == report) { if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteMagicBytes *** --->")); debugSerial->print(index); debugSerial->println(F("... OK !")); } return 1; } } } displayDetectTimer = millis() + DISPLAY_TIMEOUT + 10000; //manual disconnect if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteMagicBytes *** --->")); debugSerial->print(index); debugSerial->println(F("... Timeout!")); } return -1; // timeout } // ###################################### // ## Write Magic Double Bytes ########## // ###################################### uint8_t Genie::WriteMagicDBytes(uint8_t index, uint16_t *shorts, uint8_t len, uint8_t report) { if ( UserDoubleByteReader == NULL ) { if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) debugSerial->println(F("*** Genie Enable AttachMagicDoubleByteReader !!! ***")); return -1; } if ( !displayDetected ) return -1; uint8_t checksum; deviceSerial->write(GENIEM_WRITE_DBYTES); checksum = GENIEM_WRITE_DBYTES; deviceSerial->write(index); checksum ^= index; deviceSerial->write(len); checksum ^= len; for (int i = 0; i < len; i++) { deviceSerial->write (shorts[i] >> 8); checksum ^= shorts[i] >> 8; deviceSerial->write (shorts[i] & 0xFF); checksum ^= shorts[i] & 0xff; } deviceSerial->write(checksum); uint32_t timeout_write = millis(); if (!report) pendingACK = 1; while ( millis() - timeout_write <= GENIE_CMD_TIMEOUT ) { uint8_t command_return = DoEvents(); if (!report) { if ( command_return == GENIE_ACK ) { if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteMagicDBytes *** --->")); debugSerial->print(index); debugSerial->println(F("... ACK !")); } return 1; } if ( command_return == GENIE_NAK ) { if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteMagicDBytes *** --->")); debugSerial->print(index); debugSerial->println(F("... NAK !")); } return 0; } } else { if ( command_return == report) { if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteMagicDBytes *** --->")); debugSerial->print(index); debugSerial->println(F("... OK !")); } return 1; } } } displayDetectTimer = millis() + DISPLAY_TIMEOUT + 10000; //manual disconnect if ( ( debug_level == 6 || debug_level == 5 ) && debugSerial != NULL ) { debugSerial->print(F("*** Genie WriteMagicDBytes *** --->")); debugSerial->print(index); debugSerial->println(F("... Timeout!")); } return -1; // timeout }

My code, the event handler and control system functions are really what's important (pretty messy, it's the first version of my code that I have got to compile for the esp32). Within my timeframe I think switching IDE's might be a mistake. This is basically firmware for a drying device that runs off of a scale, infrared sensors, and to be implemented...a spectrometer using a AS7263 chip. I was using an AVR and trying to communicate with the ESP32 via uart (as well as the display), but I've had so many problems ...I figured I mine as well try and port everything to the ESP if I have to deal with the uart situation. '

Details ` #include #include //#include #include //#include #include #include #include // Network parameters const char* ssid = "cENSORED"; const char* password = "cENSORED"; //const char* ssid = "Beans Guest"; //const char* password = "dentondive"; //============================================================================== // ThingSpeak (MATLAB API) information char thingSpeakAddress[] = "api.thingspeak.com"; unsigned long channelID = cENSORED; char* readAPIKey = "cENSORED"; char* writeAPIKey = "cENSORED"; const unsigned long postingInterval = 3600000; float field[8]={500,500,500,500,500,500,500,500}; //============================================================================ const char* host = "script.google.com"; const int httpsPort = 443; String SCRIPT_ID = "cENSORED"; //============================================================================== //#include //#include // #Serial Pin 0 - // CONTROL SENSOR FOR AMBIENT TEMP #define DHTPIN 5 #define DHT2PIN 2 #define DHT3PIN 3 #define RESETLINE 19 #define LC_Clk 14 #define LC_Data 12 //Data to X axis load cell #define HEATPIN 23 // HEAT MOSFET CONTROL #define FANPIN 22 // AIRFLOW MOSFET CONTROL // #define FAN2PIN 70 // #define LM3PIN A0 // #define LM2PIN A2 //PELT // #define LM1PIN A4 // #define LM0PIN A6 // #define SDA 23 //A4 #define SCL 21 //A5 #define DHTTYPE DHT22 // // AM2302 // (AM2302), AM2321 #define DS3231_I2C_ADDRESS 0x68 // #define memADDRESS = 0x??/ find good section to store HDC.LC.calfactor, time; const String timestring = "NO TIME"; const String datestring = "NO DATE"; const String daysel = "no day"; const unsigned int minutetime = 60000; const unsigned int hourtime = 360000; int handshake; typedef struct { volatile unsigned long milcount,waitT; bool flag; } timer, *ptime; typedef struct { volatile bool statusnow; volatile bool statusold; } transferstate, *ptransferstate; typedef struct { transferstate OUT; transferstate ORIDE; bool sysflag; } heat, *pheat; typedef struct { transferstate OUT; transferstate IN; transferstate ORIDE; bool sysflag; } air, *pair; typedef struct { int oldform,newform; }formx, *pformx; typedef struct { formx FORM; int wifistate; } disp, *pdisp; typedef struct { float temp; float humid; } dhtDAT, *pdhtDAT; typedef struct { float temp; //float data[5]; float average; } tempstruct, *ptempstruct; typedef struct { bool goodrF; long calfactor; // unsigned long samples [5]; } loadc,*ploadc; typedef struct { volatile bool mode1,state; bool runningnow,done; bool startF[3]= {false,false,false}; volatile int heatT,coolT,runT= 0; int maxT = 40; float massI,massG,massT = 0.0; int masspercent; unsigned long timer = 0.0; } dryp, *pdryp; typedef struct {float spectrum[6]; float scale; float irtemp[4]; } sensorsE, *psensorsE; typedef struct { timer STATE[6]; int currentstate; } board, *pboard; typedef struct { float lmtemp[4]; board AT1280; board ESP; sensorsE ESPsens; dhtDAT INTAKE; dhtDAT EXHAUST; dhtDAT AMBIENT; air AIR; dryp DRYP; heat HEAT; disp DISP; loadc LC; } SYSstate, *pSYSstate; // DHT dht(DHTPIN,DHTTYPE); //Ambient // DHT dht2(DHT2PIN,DHTTYPE); //Power Supply // DHT dht3(DHT3PIN,DHTTYPE); // WiFiClient client; HX711_ADC LC(LC_Data, LC_Clk); Genie genie; SYSstate HDC; unsigned long lastConnectionTime,calFACTOR = 0; long lastUpdateTime,timeC,bullshit,bullshit2 = 0; void setup() { Serial.begin(115200); Serial2.begin(9600, SERIAL_8N1, 16, 17); Wire.begin(); genie.Begin(Serial2); genie.AttachEventHandler(myGenieEventHandler); // pinMode(DHTPIN,INPUT_PULLUP); // pinMode(DHT2PIN,INPUT_PULLUP); // pinMode(DHT3PIN,INPUT_PULLUP); // pinMode(LM0PIN,INPUT); // pinMode(LM1PIN,INPUT); // pinMode(LM2PIN,INPUT); // pinMode(LM3PIN,INPUT); pinMode(LC_Data,INPUT_PULLUP); pinMode(LC_Clk,OUTPUT); //CHECK THIS // pinMode(HEATPIN,OUTPUT); // // pinMode(FANPIN,OUTPUT); // pinMode(LED_BUILTIN, OUTPUT); //INTERNAL LED (Code from BLINK example), enabled below // long calValue = 210.9; ; //Load cell init // LC.begin(); // LC.start(100); // LC.setCalFactor(210.98); // LC.disableTareTimeout(); /////////////////////////////// //Dht init // dht.begin(); // dht2.begin(); // dht3.begin(); pinMode(RESETLINE, OUTPUT); //display reset digitalWrite(RESETLINE, 0); // Reset the Display via D4 delay(100); digitalWrite(RESETLINE, 1); // unReset the Display via D4 delay (4500);//let the display start up after the reset (This is important) // HDC.DRYP.runningnow = false; // HDC.DRYP.heatT=1; // genie.WriteObject(0x05, 1, 1); // genie.WriteObject(0x0F, 15, 1); // HDC.DRYP.coolT=1; // genie.WriteObject(0x05, 2, 1); // genie.WriteObject(0x0F, 16, 1); // HDC.DRYP.runT=12; // genie.WriteObject(0x05, 3, 12); // genie.WriteObject(0x0F, 17, 12); // LC.setSamplesInUse(4); bullshit =millis(); bullshit2 = millis(); HDC.ESP.currentstate=1; //testing wifie 7 12 2019 at cool beans in denton tx. //Serial.println("ESP setup procedure complete."); HDC.DRYP.timer= millis(); for(int k=0;k<6;k++) HDC.AT1280.STATE[k].milcount= millis(); }; void loop() //IF LOAD CELL SCREWS UP, I ADDED AN INTTERUPT -> TRY COMMENTING THIS OUT,but it may be necessary to keep. { genie.DoEvents(); switch(HDC.AT1280.currentstate) { case 0: if ((millis() - HDC.AT1280.STATE[0].milcount)>= 3000) { sensorupdate(); HDC.AT1280.STATE[0].milcount=millis(); }; break; case 1: break; case 2: if ((millis() - HDC.AT1280.STATE[2].milcount) >= 2000) { //displayTime(); HDC.AT1280.STATE[2].milcount = millis(); }; break; case 3: if ((millis() - HDC.AT1280.STATE[3].milcount) >= 6000) { if (HDC.ESP.STATE[2].flag!=true) { // HDC.lmtemp[0]= analogRead(LM0PIN); // HDC.lmtemp[1]= analogRead(LM1PIN); // HDC.lmtemp[2]= analogRead(LM2PIN); // HDC.lmtemp[3]= analogRead(LM3PIN); //Serial.print("lm35 a:");//Serial.println( HDC.lmtemp[0]); //Serial.print("lm35 b:");//Serial.println( HDC.lmtemp[0]); //Serial.print("lm35 c:");//Serial.println( HDC.lmtemp[0]); }; //Serial.print("lm35 d:");//Serial.println( HDC.lmtemp[0]); HDC.AT1280.STATE[3].milcount = millis(); }; // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 18, HDC.lmtemp[0]); // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 19, HDC.lmtemp[1]); // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 7, HDC.lmtemp[2]); // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 9, HDC.lmtemp[3]); break; case 4: if ((millis() - HDC.AT1280.STATE[4].milcount)>=100) { if (HDC.ESP.STATE[2].flag!=true) { LC.update(); genie.WriteObject(GENIE_OBJ_LED_DIGITS, 8, LC.getData()*100); HDC.AT1280.STATE[4].milcount=millis(); }; }; break; case 5: break; }; if (HDC.DRYP.runningnow == true) dryprog(); if ((millis() - HDC.AT1280.STATE[1].milcount) >= 2000) { fancontrol(); heatcontrol(); HDC.AT1280.STATE[1].milcount = millis(); }; }; void myGenieEventHandler(void) { genieFrame Event; genie.DequeueEvent(&Event); if (Event.reportObject.cmd == GENIE_REPORT_EVENT or Event.reportObject.cmd == GENIE_REPORT_OBJ) { if (Event.reportObject.object == GENIE_OBJ_FORM) ///// FORM NUMBER RELATED EVENTS { HDC.DISP.FORM.oldform = HDC.DISP.FORM.newform; HDC.DISP.FORM.newform = (Event.reportObject.index); HDC.AT1280.currentstate=HDC.DISP.FORM.newform; switch (HDC.DISP.FORM.newform) { case 0: //THIS IS TEMP SENSOR DATA PAGE // sensorupdate(t, t3, t3, h, h2, h3); break; case 1: //BOOTSCREEN //N, IMPLEMENT SCREEN SAVER break; case 2: if ( HDC.DISP.FORM.oldform == 5 and HDC.DRYP.runningnow == false) killdryprog(); break; case 3:// HDC.lmtemp[0]= analogRead(LM0PIN); // HDC.lmtemp[0]= analogRead(LM1PIN); // HDC.lmtemp[0]= analogRead(LM2PIN); // HDC.lmtemp[0]= analogRead(LM3PIN); //FAN AND HEAT CONTROL/DATA break; case 4: break; case 5: break; case 6: break; }; }; if (Event.reportObject.object == 30) //4D button events { switch (Event.reportObject.index) { case 2: // HDC.AIR.ORIDE.statusold = HDC.AIR.ORIDE.statusnow; HDC.AIR.ORIDE.statusnow = !HDC.AIR.ORIDE.statusnow; HDC.AIR.OUT.statusold = HDC.AIR.OUT.statusnow; HDC.AIR.OUT.statusnow = HDC.AIR.ORIDE.statusnow; genie.WriteObject(GENIE_OBJ_USER_LED, 8, HDC.AIR.OUT.statusnow); // fancontrol(); break; case 3: // HDC.HEAT.ORIDE.statusnow = genie.GetEventData(&Event); // HDC.HEAT.ORIDE.statusold = HDC.HEAT.ORIDE.statusnow; HDC.HEAT.ORIDE.statusnow = !HDC.HEAT.ORIDE.statusnow; HDC.HEAT.OUT.statusold = HDC.HEAT.OUT.statusnow; HDC.HEAT.OUT.statusnow = HDC.HEAT.ORIDE.statusnow; genie.WriteObject(GENIE_OBJ_USER_LED, 7, HDC.HEAT.ORIDE.statusnow); // heatcontrol(); break; case 5: LC.tareNoDelay(); //NoDelay(); genie.WriteStr(3,"Taring Scale. Please wait 3 seconds."); break; case 6: HDC.DRYP.mode1 = !HDC.DRYP.mode1; //genie.GetEventData(&Event); break; case 7: if ((genie.GetEventData(&Event) == true) && HDC.DRYP.startF[0] == true && HDC.DRYP.startF[1] && HDC.DRYP.startF[2]== true) { HDC.DRYP.runningnow = true; //genie.WriteStr(2,"Start time is: " + String(HDC.DRYP.startT)); HDC.DRYP.timer = millis(); genie.WriteObject(GENIE_OBJ_USER_LED, 0, true); genie.WriteObject(GENIE_OBJ_USER_LED, 10, true); genie.WriteObject(GENIE_OBJ_LED, 0, true); }; if (genie.GetEventData(&Event) == false) killdryprog(); break; case 8: //AVRtx.sendData(); break; case 9: if (HDC.DRYP.runningnow == false) HDC.DRYP.maxT = genie.GetEventData(&Event); LC.tare(); HDC.DRYP.startF[0]=true; genie.WriteObject(GENIE_OBJ_USER_LED, 3, true); //if (genie.GetEventData(&Event) == false and HDC.DRYP.runningnow == false ) // genie.WriteObject(GENIE_OBJ_USER_LED, 3, false); break; case 11: if (HDC.DRYP.runningnow == false && HDC.DRYP.startF[0]== true) { HDC.DRYP.massI = (LC.getData()); genie.WriteObject(GENIE_OBJ_LED_DIGITS, 14, HDC.DRYP.massI);//Build dryer stats HDC.DRYP.massT=(HDC.DRYP.massI*0.05); genie.WriteStr(5,String(HDC.DRYP.massI)&& "calculated for inital mass."); HDC.DRYP.startF[1]=true; genie.WriteObject(GENIE_OBJ_USER_LED,4,1); }; break; case 12: if (HDC.DRYP.runningnow == false && HDC.DRYP.startF[0]== true && HDC.DRYP.startF[1]== true) { genie.WriteObject(GENIE_OBJ_USER_LED, 6, 1); HDC.DRYP.startF[2]=true; }; break; case 14: LC.powerDown(); break; case 15: HDC.LC.calfactor = LC.getData()/50; genie.WriteStr(3,"Calibration based on 50g test weight."); genie.WriteObject(GENIE_OBJ_LED_DIGITS,13,HDC.LC.calfactor*100); LC.setCalFactor(HDC.LC.calfactor); break; case 17: HDC.DRYP.mode1 = !HDC.DRYP.mode1; case 18: LC.tareNoDelay(); break; case 19: LC.powerUp(); break; }; }; if (Event.reportObject.object == 5) /////TRACKBAR EVENTS { switch (Event.reportObject.index) { case 1 : HDC.DRYP.heatT = genie.GetEventData(&Event); genie.WriteObject(GENIE_OBJ_LED_DIGITS, 15, HDC.DRYP.heatT); break; case 2 : HDC.DRYP.coolT = genie.GetEventData(&Event); genie.WriteObject(GENIE_OBJ_LED_DIGITS, 16, HDC.DRYP.coolT); break; case 3 : HDC.DRYP.runT = genie.GetEventData(&Event); genie.WriteObject(GENIE_OBJ_LED_DIGITS, 17, HDC.DRYP.runT); break; } } if (Event.reportObject.object == 0x03) //////////Rotary switch events// { switch (Event.reportObject.index) { case 0 : HDC.DRYP.maxT = genie.GetEventData(&Event); break; }; }; }; }; void sensorupdate () { // HDC.INTAKE.humid = dht.readHumidity(); // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) // HDC.INTAKE.temp = dht.readTemperature(); // Read tempe rature as Celsius (the default) // Read temperature as Fahrenheit (isFahrenheit = true) // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 0,(HDC.INTAKE.temp)* 10); //was (float)t * 10 , removing type cast for efficiency // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 3,(HDC.INTAKE.humid) * 10); // // HDC.EXHAUST.humid = dht2.readHumidity(); // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) // HDC.EXHAUST.temp = dht2.readTemperature(); // Read temperature as Celsius (the default) // Read temperature as Fahrenheit (isFahrenheit = true) // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 1, (HDC.EXHAUST.temp)* 10); // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 4, (HDC.EXHAUST.humid) * 10); // // HDC.AMBIENT.humid = dht3.readHumidity(); // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) // HDC.AMBIENT.temp = dht3.readTemperature(); // Read temperature as Celsius (the default) // Read temperature as Fahrenheit (isFahrenheit = true) // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 2, HDC.AMBIENT.temp* 10); // genie.WriteObject(GENIE_OBJ_LED_DIGITS, 5, HDC.AMBIENT.humid* 10); //genie.WriteObject(GENIE_OBJ_LED_DIGITS, 8 , (float)(LC.getData()*10.0)); /// genie.WriteObject(0x19, 0, massnow); scope later }; byte decToBcd(byte val) { return ( (val / 10 * 16) + (val % 10) ); }; byte bcdToDec(byte val) { return ( (val / 16 * 10) + (val % 16) ); }; void fancontrol() { if (HDC.AIR.OUT.statusnow == true ) {genie.WriteObject(GENIE_OBJ_USER_LED, 2, 1); digitalWrite(FANPIN, HIGH); // turn the LED on (HIGH is the voltage level) }; if (HDC.AIR.OUT.statusnow == false ) {genie.WriteObject(GENIE_OBJ_USER_LED, 2, 0); digitalWrite(FANPIN, LOW); // turn the LED on (HIGH is the voltage level) }; if (HDC.DISP.FORM.newform == 4 and HDC.AIR.OUT.statusnow != false) { HDC.AIR.OUT.statusold=HDC.AIR.OUT.statusnow; HDC.AIR.OUT.statusnow = false; genie.WriteObject(GENIE_OBJ_USER_LED, 2, 0); digitalWrite(FANPIN, LOW); // turn the LED on (HIGH is the voltage level) }; if (HDC.AIR.ORIDE.statusnow == true) {HDC.AIR.OUT.statusold=HDC.AIR.OUT.statusnow; HDC.AIR.OUT.statusnow = true; genie.WriteObject(GENIE_OBJ_USER_LED, 2, true); digitalWrite(FANPIN, HIGH); // turn the LED on (HIGH is the voltage level) }; }; void heatcontrol() { if (HDC.HEAT.OUT.statusnow == true ) { //////////Serial.println(F("Writing HIGH to HEATPIN.")); genie.WriteObject(GENIE_OBJ_USER_LED, 1, 1); digitalWrite(HEATPIN, HIGH); // turn the LED on (HIGH is the voltage level) } ; if (HDC.HEAT.OUT.statusnow == false ) { //////////Serial.println(F("Writing LOW to HEATPIN.")); genie.WriteObject(GENIE_OBJ_USER_LED, 1, 0); digitalWrite(HEATPIN, LOW); // turn the LED on (HIGH is the voltage level) } ; }; void killdryprog() { genie.WriteObject(GENIE_OBJ_USER_LED, 3, 0); HDC.DRYP.startF[0]= false; //RESET TARE STATUS genie.WriteObject(GENIE_OBJ_USER_LED, 4, 0); HDC.DRYP.startF[1]= false; //RESET MASS STATUS HDC.DRYP.startF[2]= false; //NOT ON FORM 5 ANYMORE genie.WriteObject(GENIE_OBJ_USER_LED, 6, 0); //led on the page genie.WriteObject(GENIE_OBJ_USER_LED, 10, 0); //led on the page genie.WriteObject(0x1E,7, 0); //4D BUTTON 7 }; void dryprog () { if ((millis() - HDC.DRYP.timer) <= (HDC.DRYP.heatT*60000L)) //mins*60000ms {HDC.DRYP.state = false; }else HDC.DRYP.state = true; if ((millis() - HDC.DRYP.timer) >= ((HDC.DRYP.heatT+HDC.DRYP.coolT) * 60000L)) //(mins+mins) *60000ms HDC.DRYP.timer = millis(); //reset timer for state declaration if (HDC.DRYP.state == true) {HDC.AIR.OUT.statusold=HDC.AIR.OUT.statusnow; HDC.AIR.OUT.statusnow = true; HDC.HEAT.OUT.statusold=HDC.HEAT.OUT.statusnow; HDC.HEAT.OUT.statusnow = true; }; if (HDC.DRYP.state == false) {HDC.AIR.OUT.statusold=HDC.AIR.OUT.statusnow; HDC.AIR.OUT.statusnow = true; HDC.HEAT.OUT.statusold=HDC.HEAT.OUT.statusnow; HDC.HEAT.OUT.statusnow = false; }; }; `
stickbreaker commented 4 years ago

@kbickham Ok, I tracked down the meaning of GENIE_READ_OBJ here

If I am understanding your code, it simplifies down to:

#define GENIE_READ_OBJ 0

Serial.write((uint8_t) GENIE_READ_OBJ );

But, I don't think that is your problem. I scanned through your code, you redefine GENIE::BEGIN()

// ######################################
// ## Setup #############################
// ######################################
bool Genie::Begin(Stream &serial) {
deviceSerial = &serial;
display_uptime = millis(); // start uptime timer (ms)
genieStart = 1; // start form request on startup
ReadObject(GENIE_OBJ_FORM, (uint8_t)0x00); // send form request
uint32_t timeout_start = millis(); // timeout timer
while ( millis() - timeout_start <= 250 ) { // blocking loop, releases after 150ms to timeout, or sooner if display's detected.
if ( DoEvents() == GENIE_REPORT_OBJ && !genieStart ) return 1; // form is updated.
}
displayDetected = 0;
return 0; // timeout occured, status offline.
}

But, I never see anywhere in your code you actually call it? so the deviceSerial() stream pointer is null?

deviceSerial->write() would generate this error if deviceSerial is NULL.

This is not a problem with arduino-esp32, your code has issues.

Chuck.

kbickham commented 4 years ago

It's basically a hex command code define in a library I have to use for comms to display.I'm not I'm actually not utilizing that specific function,instead I used an event based approach sending flags from display...thank god. I found a work around, I apologize for borderline thread jacking. My compiler agrees with you. I should have initially turned the compiler flags all the way up and done work before posting. That thing gives warnings for unrelated libraries in the same parent directory that are missing returns without void type. It's working now. Appreciate your time.

stale[bot] commented 4 years ago

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

stale[bot] commented 4 years ago

[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.