From 7e6842cd1d92bacd7343ba7411d0d67a2bd58f3c Mon Sep 17 00:00:00 2001 From: livello Date: Mon, 22 Oct 2018 10:34:53 +0300 Subject: [PATCH 1/5] 1w domoticz support --- lighthub/main.cpp | 38 +++++++++++++++++++++++--------------- lighthub/main.h | 2 +- lighthub/owTerm.cpp | 13 ++++--------- platformio.ini | 8 ++++---- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/lighthub/main.cpp b/lighthub/main.cpp index 768677d..f6f68f0 100644 --- a/lighthub/main.cpp +++ b/lighthub/main.cpp @@ -554,11 +554,11 @@ void resetHard() { #ifdef _owire -void Changed(int i, DeviceAddress addr, float val) { +void Changed(int i, DeviceAddress addr, float currentTemp) { char addrstr[32] = "NIL"; //char addrbuf[17]; char valstr[16] = "NIL"; - char *owEmit = NULL; + char *owEmitString = NULL; char *owItem = NULL; SetBytes(addr, 8, addrstr); @@ -566,25 +566,33 @@ void Changed(int i, DeviceAddress addr, float val) { aJsonObject *owObj = aJson.getObjectItem(owArr, addrstr); if (owObj) { - owEmit = aJson.getObjectItem(owObj, "emit")->valuestring; + owEmitString = aJson.getObjectItem(owObj, "emit")->valuestring; - if (owEmit) { - printFloatValueToStr(val,valstr); - debugSerial<valuestring) {//DOMOTICZ json format support + debugSerial << endl << idx->valuestring << F(" Domoticz valstr:"); + char valstr[50]; + sprintf(valstr, "{\"idx\":%s,\"svalue\":\"%.1f\"}", idx->valuestring, currentTemp); + debugSerial << valstr; + mqttClient.publish(owEmitString, valstr); + return; + } +#endif - if ((val == -127.0) || (val == 85.0) || (val == 0.0)) { //ToDo: 1-w short circuit mapped to "0" celsium - return; - } strcpy_P(addrstr, outprefix); - strncat(addrstr, owEmit, sizeof(addrstr)); - //strncat(addrstr, addrbuf, sizeof(addrstr)); - + strncat(addrstr, owEmitString, sizeof(addrstr)); mqttClient.publish(addrstr, valstr); } owItem = aJson.getObjectItem(owObj, "item")->valuestring; - if (owItem) { - thermoSetCurTemp(owItem, val); ///TODO: Refactore using Items interface - } + if (owItem) + thermoSetCurTemp(owItem, currentTemp); ///TODO: Refactore using Items interface else debugSerial< Date: Tue, 23 Oct 2018 15:39:20 +0300 Subject: [PATCH 2/5] domoticz uptime, dht22, contact refactoring --- lighthub/inputs.cpp | 75 ++++++++++++++++++++++++++++----------------- lighthub/inputs.h | 3 ++ 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/lighthub/inputs.cpp b/lighthub/inputs.cpp index 31aed83..d5f2827 100644 --- a/lighthub/inputs.cpp +++ b/lighthub/inputs.cpp @@ -92,17 +92,17 @@ void Input::Parse() inType = 0; pin = 0; if (inputObj && (inputObj->type == aJson_Object)) { - aJsonObject *s; - s = aJson.getObjectItem(inputObj, "T"); - if (s) inType = static_cast(s->valueint); + aJsonObject *itemBuffer; + itemBuffer = aJson.getObjectItem(inputObj, "T"); + if (itemBuffer) inType = static_cast(itemBuffer->valueint); pin = static_cast(atoi(inputObj->name)); - s = aJson.getObjectItem(inputObj, "S"); - if (!s) { + itemBuffer = aJson.getObjectItem(inputObj, "S"); + if (!itemBuffer) { debugSerial<valueint; + if (itemBuffer) store = (inStore *) &itemBuffer->valueint; } } @@ -222,15 +222,8 @@ void Input::dht22Poll() { if (emit && temp && humidity && temp == temp && humidity == humidity) { char addrstr[100] = ""; #ifdef WITH_DOMOTICZ - aJsonObject *idx = aJson.getObjectItem(inputObj, "idx"); - if (idx && idx->valuestring) {//DOMOTICZ json format support - debugSerial << endl << idx->valuestring << F(" Domoticz valstr:"); - char valstr[50]; - sprintf(valstr, "{\"idx\":%s,\"svalue\":\"%.1f;%.0f;0\"}", idx->valuestring, temp, humidity); - debugSerial << valstr; - mqttClient.publish(emit->valuestring, valstr); - setNextPollTime(millis() + DHT_POLL_DELAY_DEFAULT); - debugSerial << F(" NextPollMillis=") << nextPollTime() << endl; + if(getIdxField()){ + publishDataToDomoticz(DHT_POLL_DELAY_DEFAULT, emit, "{\"idx\":%s,\"svalue\":\"%.1f;%.0f;0\"}", getIdxField(), temp, humidity); return; } #endif @@ -276,16 +269,23 @@ void Input::setNextPollTime(unsigned long pollTime) { } void Input::uptimePoll() { - if(nextPollTime()>millis()) + if (nextPollTime() > millis()) return; aJsonObject *emit = aJson.getObjectItem(inputObj, "emit"); if (emit) { +#ifdef WITH_DOMOTICZ + if(getIdxField()){ + publishDataToDomoticz(DHT_POLL_DELAY_DEFAULT, emit, "{\"idx\":%s,\"svalue\":\"%d\"}", getIdxField(), millis()); + return; + } +#endif + char valstr[11]; // printUlongValueToStr(valstr,millis()); - printUlongValueToStr(valstr,millis()); + printUlongValueToStr(valstr, millis()); mqttClient.publish(emit->valuestring, valstr); } - setNextPollTime(millis() +UPTIME_POLL_DELAY_DEFAULT); + setNextPollTime(millis() + UPTIME_POLL_DELAY_DEFAULT); } void Input::onCounterChanged(int i) { @@ -370,15 +370,9 @@ void Input::onContactChanged(int newValue) { aJsonObject *emit = aJson.getObjectItem(inputObj, "emit"); if (emit) { #ifdef WITH_DOMOTICZ - aJsonObject *idx = aJson.getObjectItem(inputObj, "idx"); - if (idx->valuestring) { - debugSerial << endl << idx->valuestring << F(" Domoticz valstr:"); - char valstr[80]; - char *switchCmd; - (newValue)? sprintf(valstr, "{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"On\"}", idx->valuestring) - : sprintf(valstr,"{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}",idx->valuestring); - debugSerial << valstr; - mqttClient.publish(emit->valuestring, valstr); + if (getIdxField()) { + (newValue)? publishDataToDomoticz(0, emit, "{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"On\"}", getIdxField()) + : publishDataToDomoticz(0,emit,"{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}",getIdxField()); } else #endif if (newValue) { //send set command @@ -423,3 +417,28 @@ void Input::printUlongValueToStr(char *valstr, unsigned long value) { } valstr[i]='\0'; } +bool Input::publishDataToDomoticz(int pollTimeIncrement, aJsonObject *emit, const char *format, ...) +{ +#ifdef WITH_DOMOTICZ + debugSerial << F("\nDomoticz valstr:"); + char valstr[50]; + va_list args; + va_start(args, format); + vsnprintf(valstr, sizeof(valstr) - 1, format, args); + va_end(args); + debugSerial << valstr; + mqttClient.publish(emit->valuestring, valstr); + if (pollTimeIncrement) + setNextPollTime(millis() + pollTimeIncrement); + debugSerial << F(" NextPollMillis=") << nextPollTime() << endl; + +#endif + return true; +} + +char* Input::getIdxField() { + aJsonObject *idx = aJson.getObjectItem(inputObj, "idx"); + if(idx&&idx->valuestring) + return idx->valuestring; + return nullptr; +} diff --git a/lighthub/inputs.h b/lighthub/inputs.h index 262728f..7803325 100644 --- a/lighthub/inputs.h +++ b/lighthub/inputs.h @@ -124,4 +124,7 @@ protected: void uptimePoll(); void printUlongValueToStr(char *valstr, unsigned long value); + bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...); + + char* getIdxField(); }; From 9ea9ad8698287a66fb1b853429e8785ac5796fd2 Mon Sep 17 00:00:00 2001 From: livello Date: Wed, 7 Nov 2018 01:25:28 +0300 Subject: [PATCH 3/5] refactoring. stm32 minimal support --- lighthub/item.cpp | 8 ++++-- lighthub/main.cpp | 44 +++++++++++++++++----------- lighthub/main.h | 6 +++- lighthub/options.h | 2 ++ lighthub/utils.cpp | 7 ++++- platformio.ini | 72 ++++++++++++++++++++++++---------------------- 6 files changed, 84 insertions(+), 55 deletions(-) diff --git a/lighthub/item.cpp b/lighthub/item.cpp index adc0318..3cf51f5 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -23,16 +23,17 @@ e-mail anklimov@gmail.com #include "utils.h" #ifdef _dmxout - #include "dmx.h" #include "FastLED.h" - #endif +#ifndef MODBUS_DISABLE #include +#endif #include + short modbusBusy = 0; extern aJsonObject *pollingItem; @@ -1266,7 +1267,10 @@ int Item::SendStatus(short cmd, short n, int *Par, boolean deffered) { if (Par) for (short i = 0; i < n; i++) { char num[4]; + #ifndef FLASH_64KB snprintf(num, sizeof(num), "%d", Par[i]); + #endif + itoa(Par[i],num,10); strncat(valstr, num, sizeof(valstr)); if (i != n - 1) { strcpy(num, ","); diff --git a/lighthub/main.cpp b/lighthub/main.cpp index f6f68f0..4d77acf 100644 --- a/lighthub/main.cpp +++ b/lighthub/main.cpp @@ -94,12 +94,13 @@ WiFiClient ethClient; #endif #ifdef ARDUINO_ARCH_STM32F1 +#include "HttpClient.h" //#include //#include "UIPEthernet.h" //#include "UIPUdp.h" #include #include -#include "HttpClient.h" + #include "Dns.h" //#include "utility/logging.h" #include @@ -126,10 +127,18 @@ aJsonObject *items = NULL; aJsonObject *inputs = NULL; aJsonObject *mqttArr = NULL; +#ifndef MODBUS_DISABLE aJsonObject *modbusArr = NULL; +#endif +#ifdef _owire aJsonObject *owArr = NULL; +#endif +#ifdef _dmxout aJsonObject *dmxArr = NULL; +#endif +#ifdef SYSLOG_ENABLE aJsonObject *udpSyslogArr = NULL; +#endif unsigned long nextPollingCheck = 0; unsigned long nextInputCheck = 0; @@ -378,7 +387,6 @@ void ip_ready_config_loaded_connecting_to_broker() { mqttClient.setCallback(mqttCallback); debugSerial<child; thermoItem; thermoItem = thermoItem->next) { if (isThermostatWithMinArraySize(thermoItem, 5)) { aJsonObject *thermoExtensionArray = aJson.getArrayItem(thermoItem, I_EXT); diff --git a/lighthub/main.h b/lighthub/main.h index 1ee34b2..b8c8ea4 100644 --- a/lighthub/main.h +++ b/lighthub/main.h @@ -55,13 +55,17 @@ #include #include "utils.h" #include -#include #include "aJSON.h" #include #include "stdarg.h" #include "item.h" #include "inputs.h" + +#ifndef MODBUS_DISABLE +#include +#endif + #ifndef ARDUINO_ARCH_STM32F1 #include "FastLED.h" #endif diff --git a/lighthub/options.h b/lighthub/options.h index 87bbde6..3654d89 100644 --- a/lighthub/options.h +++ b/lighthub/options.h @@ -158,6 +158,8 @@ #ifndef Wiz5500 #define W5100_ETHERNET_SHIELD +#else +#define W5500_ETHERNET_SHIELD #endif #define eol "\n" diff --git a/lighthub/utils.cpp b/lighthub/utils.cpp index db88ab5..ba8eaac 100644 --- a/lighthub/utils.cpp +++ b/lighthub/utils.cpp @@ -100,11 +100,13 @@ extern char _end; extern "C" char *sbrk(int i); unsigned long freeRam() { +#ifndef DISABLE_FREERAM_PRINT char *heapend = sbrk(0); register char *stack_ptr asm( "sp" ); struct mallinfo mi = mallinfo(); - return stack_ptr - heapend + mi.fordblks; +#endif + return 7777; } #endif @@ -156,6 +158,8 @@ void printFloatValueToStr(float value, char *valstr) { #define ARDBUFFER 16 //Buffer for storing intermediate strings. Performance may vary depending on size. +#ifndef ARDUINO_ARCH_STM32F1 + int log(const char *str, ...)//TODO: __FlashStringHelper str support { int i, count=0, j=0, flag=0; @@ -207,6 +211,7 @@ int log(const char *str, ...)//TODO: __FlashStringHelper str support Serial.println(); //Print trailing newline return count + 1; //Return number of arguments detected } +#endif #pragma message(VAR_NAME_VALUE(debugSerial)) diff --git a/platformio.ini b/platformio.ini index 7fc4ad3..b7e88a6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,19 +9,19 @@ ; http://docs.platformio.org/page/projectconf.html [platformio] src_dir = lighthub -env_default = +;env_default = ; megaatmega2560 ; megaatmega2560-net ; due ; esp8266 ; esp32 ; megaatmega2560-5500 - due-5500 +; due-5500 ; controllino ; stm32 -build_dir = /tmp/pioenvs -libdeps_dir = /tmp/piolibdeps +;build_dir = /tmp/pioenvs +;libdeps_dir = /tmp/piolibdeps [env:esp32] platform = espressif32 @@ -247,35 +247,37 @@ lib_deps = https://github.com/livello/PrintEx#is-select-redecl ;TODO:STM32 compilation problems -;[env:stm32] -;platform = ststm32 -;framework = arduino -;board = nucleo_f103rb -;upload_protocol = stlink -;debug_tool = stlink -;build_flags = !bash check_custom_build_flags_stm32.sh -;lib_ignore = -; DHT sensor library for ESPx -; DmxDue -; DueFlashStorage -; ESP-Dmx -; WifiManager -; FastLED -; Ethernet -;lib_deps = +[env:stm32] +platform = ststm32 +framework = arduino +board = nucleo_f103rb +upload_protocol = stlink +debug_tool = stlink +build_flags = !bash check_custom_build_flags_stm32.sh +lib_ignore = + DHT sensor library for ESPx + DmxDue + DueFlashStorage + ESP-Dmx + WifiManager + FastLED + Ethernet + https://github.com/anklimov/Ethernet + DMXSerial + DmxSimple + httpClient + SD + PrintEx + Ethernet2 + Artnet + + +lib_deps = ; DallasTemperature -; https://github.com/anklimov/aJson -; https://github.com/anklimov/CmdArduino -; ArduinoHttpClient -; https://github.com/anklimov/ModbusMaster -;; https://github.com/Serasidis/Ethernet_STM.git -;; https://github.com/livello/Ethernet_STM.git -; https://github.com/knolleary/pubsubclient.git -; Adafruit Unified Sensor -; DHT sensor library -;; https://github.com/anklimov/DMXSerial -;; Syslog -;; https://github.com/No3x/Syslog.git -; https://github.com/arcao/Syslog.git -;; UIPEthernet -; Streaming + https://github.com/anklimov/aJson + https://github.com/anklimov/CmdArduino + ArduinoHttpClient + https://github.com/knolleary/pubsubclient.git + Adafruit Unified Sensor + DHT sensor library + Streaming From 23f2e600792e60747755363eb8099525282e1bb9 Mon Sep 17 00:00:00 2001 From: livello Date: Wed, 7 Nov 2018 13:49:30 +0300 Subject: [PATCH 4/5] fix flash_64kb error. debugSerial in Item.cpp --- lighthub/item.cpp | 43 ++++++++++++++----------------------------- lighthub/item.h | 2 +- platformio.ini | 1 - 3 files changed, 15 insertions(+), 31 deletions(-) diff --git a/lighthub/item.cpp b/lighthub/item.cpp index 3cf51f5..8e6859c 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -81,20 +81,10 @@ void Item::Parse() { for (int i = aJson.getArraySize(itemArr); i < 4; i++) aJson.addItemToArray(itemArr, aJson.createItem( int(defval[i]))); //Enlarge item to 4 elements. VAL=int if no other definition in conf - - itemType = aJson.getArrayItem(itemArr, I_TYPE)->valueint; itemArg = aJson.getArrayItem(itemArr, I_ARG); itemVal = aJson.getArrayItem(itemArr, I_VAL); - -/* - Serial.print(F(" Item:")); - Serial.print(itemArr->name); - Serial.print(F(" T:")); - Serial.print(itemType); - Serial.print(F(" =")); - Serial.println(getArg()); - */ + debugSerial << (F(" Item:") << itemArr->name << F(" T:") << itemType << F(" =") << getArg() << eol; } } @@ -117,13 +107,12 @@ uint8_t Item::getCmd(bool ext) { } -void Item::setCmd(uint8_t cmd) { - aJsonObject *t = aJson.getArrayItem(itemArr, I_CMD); - if (t) +void Item::setCmd(uint8_t cmdValue) { + aJsonObject *itemCmd = aJson.getArrayItem(itemArr, I_CMD); + if (itemCmd) { - t->valueint = cmd; - Serial.print(F("SetCmd:")); - Serial.println(cmd); + itemCmd->valueint = cmdValue; + debugSerial<type != aJson_Int) return; - // Serial.print(F(" Store ")); - // Serial.print(F(" Val=")); - // Serial.println(par); + debugSerial<")); - Serial.println(valstr); + debugSerial<")< Date: Fri, 9 Nov 2018 02:12:53 +0300 Subject: [PATCH 5/5] freeRam stub removed. debugSerial + small refactoring and code format --- lighthub/item.cpp | 254 ++++++++++++++++----------------------------- lighthub/utils.cpp | 13 +-- 2 files changed, 93 insertions(+), 174 deletions(-) diff --git a/lighthub/item.cpp b/lighthub/item.cpp index 8e6859c..fd05477 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -84,7 +84,7 @@ void Item::Parse() { itemType = aJson.getArrayItem(itemArr, I_TYPE)->valueint; itemArg = aJson.getArrayItem(itemArr, I_ARG); itemVal = aJson.getArrayItem(itemArr, I_VAL); - debugSerial << (F(" Item:") << itemArr->name << F(" T:") << itemType << F(" =") << getArg() << eol; + debugSerial << F(" Item:") << itemArr->name << F(" T:") << itemType << F(" =") << getArg() << eol; } } @@ -154,7 +154,7 @@ long int Item::getVal() //Return Val if val is int or first elem of Value array void Item::setVal(short n, int par) // Only store if VAL is array defined in config to avoid waste of RAM { if (!itemVal || itemVal->type!=aJson_Array) return; - Serial.print(F(" Store p="));Serial.print(n);Serial.print(F(" Val="));Serial.println(par); + debugSerial<type == aJson_Array) { - Serial.println(F("Grp check: ")); + debugSerial<child; while (i) { Item it(i->valuestring); if (it.isValid() && it.isActive()) { - Serial.println(F("Active")); + debugSerial<next; @@ -723,8 +686,8 @@ int Item::isActive() { case CH_PWM: val = st.aslong; } //switch - //Serial.print(F(":=")); - //Serial.println(val); + //debugSerial<")); - Serial.print(_reg, HEX); - Serial.print(F("(T:")); - Serial.print(_regType); - Serial.print(F("):")); - Serial.println(value, HEX); - + debugSerial<")<<_HEX(_reg)<type == aJson_Array) - { aJsonObject *airGateObj = aJson.getArrayItem(itemArg, 1); - if (airGateObj) { - int val = 100; - Item item(airGateObj->valuestring); - if (item.isValid()) item.Ctrl(0,1,&val); - } - } - Serial.println(); - } else { - Serial.print(F("Modbus polling error=")); - Serial.println(result, HEX); - } + if (RPM && itemArg->type == aJson_Array) { + aJsonObject *airGateObj = aJson.getArrayItem(itemArg, 1); + if (airGateObj) { + int val = 100; + Item item(airGateObj->valuestring); + if (item.isValid()) + item.Ctrl(0, 1, &val); + } + } + } else + debugSerial << F("Modbus polling error=") << _HEX(result) << eol; if (node.getResponseBuffer(0) & 8) //Active fault { @@ -997,40 +932,33 @@ int Item::checkFM() { // do something with data if read is successful if (result == node.ku8MBSuccess) { - Serial.print(F(" PI Val :")); + debugSerial << F(" PI Val :"); for (j = 0; j < 4; j++) { data = node.getResponseBuffer(j); - Serial.print(data); - Serial.print(F("-")); - + debugSerial << data << F("-"); } - + debugSerial << eol; int set = node.getResponseBuffer(0); - float fset; - float ftemp; - if (set) aJson.addNumberToObject(out, "set", fset =set * a + b); - aJson.addNumberToObject(out, "t", ftemp =(int) node.getResponseBuffer(1) * a + b); + float ftemp, fset = set * a + b; + if (set) + aJson.addNumberToObject(out, "set", fset); + aJson.addNumberToObject(out, "t", ftemp = (int) node.getResponseBuffer(1) * a + b); // aJson.addNumberToObject(out,"d", (int) node.getResponseBuffer(2)*a+b); int pwr = node.getResponseBuffer(3); - if (pwr > 0) aJson.addNumberToObject(out, "pwr", pwr / 10.); else aJson.addNumberToObject(out, "pwr", 0); + if (pwr > 0) + aJson.addNumberToObject(out, "pwr", pwr / 10.); + else aJson.addNumberToObject(out, "pwr", 0); - if (ftemp>FM_OVERHEAT_CELSIUS && set) - { + if (ftemp > FM_OVERHEAT_CELSIUS && set) { mqttClient.publish("/alarm/ovrht", itemArr->name); Ctrl(CMD_OFF); //Shut down - } - Serial.println(); - } else { - Serial.print(F("Modbus polling error=")); - Serial.println(result, HEX); - } - - + } + } else + debugSerial << F("Modbus polling error=") << _HEX(result); outch = aJson.print(out); mqttClient.publish(addrstr, outch); free(outch); aJson.deleteItem(out); - modbusBusy = 0; } @@ -1038,7 +966,7 @@ boolean Item::checkModbusRetry() { int cmd = getCmd(true); if (cmd & CMD_RETRY) { // if last sending attempt of command was failed int val = getVal(); - Serial.println(F("Retrying CMD")); + debugSerial<type != aJson_Array) || ((numpar = aJson.getArraySize(itemArg)) < 2)) { - Serial.println(F("Illegal arguments")); + debugSerial<= (MODBUS_CMD_ARG_REG_TYPE+1)) _regType = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_REG_TYPE)->valueint; // short mask = getArg(2); - // Serial.print(F("Modbus polling ")); - // Serial.print(addr); - // Serial.print(F("=>")); - // Serial.print(reg, HEX); - // Serial.print(F("(T:")); - // Serial.print(_regType); - // Serial.println(F(")")); + // debugSerial<")); + // debugSerial<name); - Serial.print(F(" Val: ")); - Serial.println(data, HEX); + debugSerial << F("MB: ") << itemArr->name << F(" Val: ") << _HEX(data) << eol; checkModbusDimmer(data); - } else { - Serial.print(F("Modbus polling error=")); - Serial.println(result, HEX); - } - + } else + debugSerial << F("Modbus polling error=") << _HEX(result) << eol; modbusBusy = 0; // Looking 1 step ahead for modbus item, which uses same register @@ -1118,9 +1040,9 @@ int Item::checkModbusDimmer() { nextItem.getArg(1) == reg) { nextItem.checkModbusDimmer(data); pollingItem = pollingItem->next; - if (!pollingItem) pollingItem = items->child; + if (!pollingItem) + pollingItem = items->child; } - } @@ -1138,7 +1060,7 @@ int Item::checkModbusDimmer(int data) { if (maxVal) d = map(d, 0, maxVal, 0, 100); int cmd = getCmd(); - //Serial.println(d); + //debugSerial<> 4, HEX); - Serial.print(addr[i] & 0x0f, HEX); + debugSerial<<_HEX(addr[i] >> 4); + debugSerial<<_HEX(addr[i] & 0x0f); } if (newline) - Serial.println(); + debugSerial<