2nd Salinity module w/Cloud Wifi Hub

Expansion modules and attachments
User avatar
Posts: 86
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD
PostPosted: Thu Mar 14, 2019 12:28 pm
Hello Roberto,

I know it's not possible to have two salinity probes with a single RA* but is it possible to directly program my Cloud Wifi Hub to directly read a salinity module/probe? Like many others, I'd like to use it at my remote mixing station which I'm trying to automate.

When we were setting up a 2nd dimming module with my Cloud WiFi Hub (used with an RA*) in the below thread,

viewtopic.php?f=12&t=6742&start=30

You mentioned that I'd have to program the Cloud wifi hub code itself to get lightening effects to work with it - not trying this just yet as my lights are functioning correctly and the room is not setup for that kind of show :D .
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink

Posts: 12459
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Thu Mar 14, 2019 4:58 pm
Yes, each cloud wifi hub can be used to have an additional salinity module.
Roberto.
User avatar
Posts: 86
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD
PostPosted: Thu Mar 14, 2019 7:05 pm
Nice! Could you please help me set it up?

I generated the following code with the Wizard:

Code: Select all
#include <Wire.h>
#include <SPI.h>
#include <WiFi101.h>
#include <PubSubClient.h>
#include <RA_CustomSettings.h>
#include <CloudGlobals.h>
#include <OneWire.h>

// ***********************************************************************
// Change fallback ports below
// Fallback ports will be turned on when cloud connection is lost
// Add each port separated by a |
// For example, if you would like for port 1 and port 5 of Relay Box 1 to be turned on when cloud connection is lost,
// you should add Port1Bit | Port5Bit
// It would look like this:
// #define Relay1FallBack Port1Bit | Port5Bit

#define Relay1FallBack 30
#define Relay2FallBack 0
#define Relay3FallBack 0
#define Relay4FallBack 0
#define Relay5FallBack 0
#define Relay6FallBack 0
#define Relay7FallBack 0
#define Relay8FallBack 0

// Redirect expansion modules to another custom expansion field.
// This is only required if you have multiple modules of the same parameter.
// For example, if you have one Cloud module with an existing salinity module already and wants to add another Cloud module
// with anoter salinity module and report those readings as a Custom Expansion Module 1
// In this case you have to change the CloudCustomModule1 to CUSTOM_SALINITY.
// The values that can be entered are:
// CUSTOM_NONE   0
// CUSTOM_SALINITY   1
// CUSTOM_ORP   2
// CUSTOM_PHEXP   3
// CUSTOM_WL   4
// CUSTOM_MULTI_WL1   5
// CUSTOM_MULTI_WL2   6
// CUSTOM_MULTI_WL3   7
// CUSTOM_MULTI_WL4   8

#define CloudCustomModule1  CUSTOM_NONE
#define CloudCustomModule2  CUSTOM_NONE
#define CloudCustomModule3  CUSTOM_NONE
#define CloudCustomModule4  CUSTOM_NONE
#define CloudCustomModule5  CUSTOM_NONE
#define CloudCustomModule6  CUSTOM_NONE
#define CloudCustomModule7  CUSTOM_NONE
#define CloudCustomModule8  CUSTOM_NONE

// Assign Temperature probes ID
// Only assign temperature probes IDs that you currently are not using in the head unit.
// If you have a total of more than 3 probes, make sure to add the following line on the setup section of the head unit code:
// ReefAngel.AddExtraTempProbes();
// For example, if you only have 1 probe connected to the head unit, assign IDs 2 and 3.
// If you have 2 probes in the head unit and 2 probes in the Cloud Wifi Hub, you must add the above line and you would assign
// IDs 3 and 4.
// Assign ID 0 to unused probes in the Hub.

byte TempProbeIDs[] = {2, 0};

// Do not change anything below
// ***********************************************************************
#define LED_GREEN 7
#define LED_BLUE 6
#define LED_RED 0
#define TempPin 5

unsigned long wifi_connection = millis();
int status = WL_IDLE_STATUS;
byte data[2];
byte data2[12];
byte addr[8];
byte addr1[8];
byte addr2[8];

OneWire  ds(TempPin);

void MQTTSubCallback(char* topic, byte* payload, unsigned int length);

PubSubClient MQTTClient(MQTTServer, MQTTPORT, MQTTSubCallback, mqttclient);

void setup()
{
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  digitalWrite(LED_GREEN, HIGH);
  digitalWrite(LED_BLUE, LOW);
  digitalWrite(LED_RED, LOW);

  wdt_initialize();
  wdt_enable();
  randomSeed(analogRead(0));
  Serial.begin(57600);
  Serial.setTimeout(100);
  delay(1500);
  Serial.println("Init");
  Wire.begin();
  FoundIP = false;
  MQTTReconnectmillis = millis();
  MQTTSendmillis = millis();

  SalinityFound = false;
  ORPFound = false;
  PHExpFound = false;
  WLFound = false;
  MultiWLFound = false;
  HumidityFound = false;

  sprintf(pub_salinity, "sal");
  sprintf(pub_orp, "orp");
  sprintf(pub_phexp, "phe");
  sprintf(pub_wl, "wl");
  sprintf(pub_multiwl, "wl");
  sprintf(pub_humidity, "hum");

  // Temperature
  byte count = 0;
  while (ds.search(addr))
  {
    if (addr[0] == 0x28)
    {
      count++;
      if (count == 1) memcpy(addr1, addr, 8);
      if (count == 2) memcpy(addr2, addr, 8);
    }
  }
  ds.reset_search();
  Serial.print(count);
  Serial.println(" temperature probe(s) found");

  // Relay
  for ( byte EID = 0; EID < MAX_RELAY_EXPANSION_MODULES; EID++ )
  {
    RelayDataE[EID] = 0;
    RelayMaskOnE[EID] = 0;
    RelayMaskOffE[EID] = 0xff;
  }
  RelayFallBackE[0] = Relay1FallBack;
  RelayFallBackE[1] = Relay2FallBack;
  RelayFallBackE[2] = Relay3FallBack;
  RelayFallBackE[3] = Relay4FallBack;
  RelayFallBackE[4] = Relay5FallBack;
  RelayFallBackE[5] = Relay6FallBack;
  RelayFallBackE[6] = Relay7FallBack;
  RelayFallBackE[7] = Relay8FallBack;

  // Dimming
  lastcrc = -1;
  for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ )
  {
    ExpansionChannel[a] = 0;
    ExpansionChannelOverride[a] = 255;
  }

  // IO
  Params.IO = 63;
  OldParams.IO = 63;

  // Leak
  Params.Leak = 0;
  OldParams.Leak = 0;

  // ORP
  Params.ORP = 0;
  OldParams.ORP = 0;
  ORPCal = false;
  ORPMin = memory_read_int(Mem_I_ORPMin);
  if (ORPMin==65535) ORPMin=0;
  ORPMax = memory_read_int(Mem_I_ORPMax);
 
  // Salinity
  Params.Salinity = 0;
  OldParams.Salinity = 0;
  SalCal = false;
  SalMax = memory_read_int(Mem_I_SalMax);

  // pH Exp
  Params.PHExp = 0;
  OldParams.PHExp = 0;
  PHExpCal = false;
  PHExpMin = memory_read_int(Mem_I_PHExpMin);
  if (PHExpMin==65535) PHExpMin=0;
  PHExpMax = memory_read_int(Mem_I_PHExpMax);

  // Humidity
  Params.Humidity = 0;
  OldParams.Humidity = 0;
 
  // Water Level
  for (int a = 0; a < WL_CHANNELS; a++)
  {
    Params.WL[a] = 0;
    OldParams.WL[a] = 0;
    WLCal[a] = false;
  }
  WLMin[0] = memory_read_int(Mem_I_WaterLevelMin);
  WLMax[0] = memory_read_int(Mem_I_WaterLevelMax);
  WLMin[1] = memory_read_int(Mem_I_WaterLevel1Min);
  WLMax[1] = memory_read_int(Mem_I_WaterLevel1Max);
  WLMin[2] = memory_read_int(Mem_I_WaterLevel2Min);
  WLMax[2] = memory_read_int(Mem_I_WaterLevel2Max);
  WLMin[3] = memory_read_int(Mem_I_WaterLevel3Min);
  WLMax[3] = memory_read_int(Mem_I_WaterLevel3Max);
  WLMin[4] = memory_read_int(Mem_I_WaterLevel4Min);
  WLMax[4] = memory_read_int(Mem_I_WaterLevel4Max);

  for (int a=0; a<5; a++)
  {
    if (WLMin[a]==65535) WLMin[a]=0;
  }
  ApplyCalibration(1, CloudCustomModule1);
  ApplyCalibration(2, CloudCustomModule2);
  ApplyCalibration(3, CloudCustomModule3);
  ApplyCalibration(4, CloudCustomModule4);
  ApplyCalibration(5, CloudCustomModule5);
  ApplyCalibration(6, CloudCustomModule6);
  ApplyCalibration(7, CloudCustomModule7);
  ApplyCalibration(8, CloudCustomModule8);

  sprintf(clientid, "%s%02d", CLOUD_USERNAME, random(10000));
  sprintf(pub_buffer, "%s/in", CLOUD_USERNAME);
  sprintf(sub_buffer, "%s/out/#", CLOUD_USERNAME);
  Serial.println("Start");
}

void loop()
{
  wdt_reset();
  status = WiFi.status();
  while ( status != WL_CONNECTED) {
    digitalWrite(LED_BLUE, LOW);
    if (millis() - wifi_connection > 1000)
    {
      wifi_connection = millis();
      Serial.print("Attempting to connect to Network named: ");
      Serial.println(WIFI_SSID);                   // print the network name (SSID);
      if (WiFi.begin(WIFI_SSID, WIFI_PASS) == WL_CONNECTED)
      {
        status = WiFi.status();
        server.begin();                           // start the web server on port 2000
        printWifiStatus();                        // you're connected now, so print out the status
        digitalWrite(LED_BLUE, HIGH);
      }
    }
  }

  MQTTClient.loop();
  if (millis() - MQTTReconnectmillis > 5000)
  {
    MQTTReconnectmillis = millis();
    if (!MQTTClient.connected())
    {
      digitalWrite(LED_RED, LOW);
      Serial.println(F("MQTT Connecting..."));
      wdt_reset();
      if (MQTTClient.connect(clientid, CLOUD_USERNAME, CLOUD_PASSWORD))
      {
        Serial.println(F("MQTT succeeded"));
        digitalWrite(LED_RED, HIGH);
        MQTTClient.subscribe(sub_buffer);
        Publish(pub_buffer, "all:0");
        wdt_reset();
      }
      else
      {
        Serial.println(F("MQTT failed"));
        MQTTClient.disconnect();
      }
    }
  }

  // Relay
  for ( byte EID = 0; EID < MAX_RELAY_EXPANSION_MODULES; EID++ )
  {
    byte TempRelay = RelayDataE[EID];
    TempRelay &= RelayMaskOffE[EID];
    TempRelay |= RelayMaskOnE[EID];
    if (!MQTTClient.connected())
      TempRelay = RelayFallBackE[EID];
    Wire.beginTransmission(I2CExpModule + EID);
    Wire.write(~TempRelay);  // MSB
    Wire.endTransmission();
  }

  // Dimming
  byte thiscrc = 0;
  for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ )
  {
    thiscrc += ExpansionChannel[a] * (a + 1);
    thiscrc += ExpansionChannelOverride[a] * (a + 1);
  }
  if (millis() % 60000 < 200) lastcrc = -1;
  if (lastcrc != thiscrc || millis() < 5000)
  {
    lastcrc = thiscrc;
    // setup PCA9685 for data receive
    // we need this to make sure it will work if connected ofter controller is booted, so we need to send it all the time.
    Wire.beginTransmission(I2CPWM_PCA9685);
    Wire.write((uint8_t)0);
    Wire.write(0xa1);
    Wire.endTransmission();
    for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ )
    {
      int data;
      if (ExpansionChannelOverride[a] <= 100)
        data = ExpansionChannelOverride[a] * 40.96;
      else
        data = ExpansionChannel[a] * 40.96;
      Wire.beginTransmission(I2CPWM_PCA9685);
      Wire.write(0x8 + (4 * a));
      Wire.write(data & 0xff);
      Wire.write(data >> 8);
      Wire.endTransmission();
    }
  }

  if (MQTTClient.connected())
  {
    digitalWrite(LED_RED, HIGH);

    // IO
    Wire.requestFrom(I2CIO_PCF8574, 1);
    if (Wire.available())
      Params.IO = Wire.read();
    if (Params.IO != OldParams.IO)
    {
      OldParams.IO = Params.IO;
      sprintf(buffer, "io:%d", Params.IO);
      Publish(pub_buffer, buffer);
    }

    // Leak
    int iLeak = 0;
    Wire.requestFrom(I2CLeak, 2);
    if (Wire.available())
    {
      iLeak = Wire.read();
      iLeak = iLeak << 8;
      iLeak += Wire.read();
      Params.Leak = iLeak > 2000;
    }
    if (Params.Leak != OldParams.Leak)
    {
      OldParams.Leak = Params.Leak;
      sprintf(buffer, "leak:%d", Params.Leak);
      Publish(pub_buffer, buffer);
    }

    if (millis() - Paramsmillis > 1000)
    {
      Paramsmillis = millis();

      // Temperature
      if (addr1[0] != 0)
      {
        ds.reset();
        ds.select(addr1);
        ds.write(0xBE);         // Read Scratchpad
        for (byte i = 0; i < 2; i++)
        {
          data[i] = ds.read();
        }
        Params.Temp[1] = (data[1] << 8) + data[0]; //take the two bytes from the response relating to temperature
        Params.Temp[1] = Params.Temp[1] / 1.6;
        if (Params.Temp[1] == 0) Params.Temp[1] = 0;
        if (Params.Temp[1] > 850) Params.Temp[1] = 0;
        Params.Temp[1] = Params.Temp[1] * 1.8 + 320;
        if (Params.Temp[1] != OldParams.Temp[1])
        {
          OldParams.Temp[1] = Params.Temp[1];
          sprintf(buffer, "t:%d:%d",TempProbeIDs[0], Params.Temp[1]);
          if (TempProbeIDs[0]!=0) Publish(pub_buffer, buffer);
        }
      }
      if (addr2[0] != 0)
      {
        ds.reset();
        ds.select(addr2);
        ds.write(0xBE);         // Read Scratchpad
        for (byte i = 0; i < 2; i++)
        {
          data[i] = ds.read();
        }
        Params.Temp[2] = (data[1] << 8) + data[0]; //take the two bytes from the response relating to temperature
        Params.Temp[2] = Params.Temp[2] / 1.6;
        if (Params.Temp[2] == 0) Params.Temp[2] = 0;
        if (Params.Temp[2] > 850) Params.Temp[2] = 0;
        Params.Temp[2] = Params.Temp[2] * 1.8 + 320;
        if (Params.Temp[2] != OldParams.Temp[2])
        {
          OldParams.Temp[2] = Params.Temp[2];
          sprintf(buffer, "t:%d:%d",TempProbeIDs[1], Params.Temp[2]);
          if (TempProbeIDs[1]!=0) Publish(pub_buffer, buffer);
        }
      }

      // ORP
      unsigned long temporp = 0;
      int iORP = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CORP, 2);
        if (Wire.available())
        {
          iORP = Wire.read();
          iORP = iORP << 8;
          iORP += Wire.read();
        }
        temporp += iORP;
      }
      temporp = temporp / 20;
      if (temporp != 0)
      {
        Params.ORP = map(temporp, ORPMin, ORPMax, 0, 470); // apply the calibration to the sensor reading
        Params.ORP = constrain(Params.ORP, 0, 550);
        if (pub_orp[0] == 'o') ORPFound = true;
      }
      if (ORPCal)
      {
        sprintf(buffer, "%sc:%d", pub_orp, temporp);
        Publish(pub_buffer, buffer);
      }
      else
      {
        if (Params.ORP != OldParams.ORP)
        {
          OldParams.ORP = Params.ORP;
          sprintf(buffer, "%s:%d", pub_orp, Params.ORP);
          Publish(pub_buffer, buffer);
        }
      }

      // Salinity
      unsigned long tempsal = 0;
      int iSAL = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CSalinity, 2);
        if (Wire.available())
        {
          iSAL = Wire.read();
          iSAL = iSAL << 8;
          iSAL += Wire.read();
        }
        tempsal += iSAL;
      }
      tempsal = tempsal / 20;
      if (tempsal != 0)
      {
        Params.Salinity = map(tempsal, 0, SalMax, 60, 350); // apply the calibration to the sensor reading
        if (pub_salinity[0] == 's') SalinityFound = true;
      }
      if (SalCal)
      {
        sprintf(buffer, "%sc:%d", pub_salinity, tempsal);
        Publish(pub_buffer, buffer);
      }
      else
      {
        if (Params.Salinity != OldParams.Salinity)
        {
          OldParams.Salinity = Params.Salinity;
          sprintf(buffer, "%s:%d", pub_salinity, Params.Salinity);
          Publish(pub_buffer, buffer);
        }
      }

      // pH Exp
      unsigned long tempphexp = 0;
      int iPHExp = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CPH, 2);
        if (Wire.available())
        {
          iPHExp = Wire.read();
          iPHExp = iPHExp << 8;
          iPHExp += Wire.read();
        }
        tempphexp += iPHExp;
      }
      tempphexp = tempphexp / 20;
      if (tempphexp != 0)
      {
        Params.PHExp = map(tempphexp, PHExpMin, PHExpMax, 700, 1000); // apply the calibration to the sensor reading
        Params.PHExp = constrain(Params.PHExp, 100, 1400);
        if (pub_phexp[0] == 'p') PHExpFound = true;
      }
      if (PHExpCal)
      {
        sprintf(buffer, "%sc:%d", pub_phexp, tempphexp);
        Publish(pub_buffer, buffer);
      }
      else
      {
        if (Params.PHExp != OldParams.PHExp)
        {
          OldParams.PHExp = Params.PHExp;
          sprintf(buffer, "%s:%d", pub_phexp, Params.PHExp);
          Publish(pub_buffer, buffer);
        }
      }

      // PAR
      unsigned long temppar = 0;
      int iPAR = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CPAR, 2);
        if (Wire.available())
        {
          iPAR = Wire.read();
          iPAR = iPAR << 8;
          iPAR += Wire.read();
        }
        temppar += iPAR;
      }
      temppar = temppar / 20;
      if (temppar != 0)
      {
        temppar *= 5000; // apply the calibration to the sensor reading
        temppar /= 8192;
        Params.PAR = temppar;
      }
      if (Params.PAR != OldParams.PAR)
      {
        OldParams.PAR = Params.PAR;
        sprintf(buffer, "par:%d", Params.PAR);
        Publish(pub_buffer, buffer);
      }

      // Humidity
      int iHumidity = 0;
      int reply[10];
     
      Wire.beginTransmission(I2CHumidity);
      Wire.endTransmission();  // For some reason, it needs this to work??? Bug with sensor??
      Wire.beginTransmission(I2CHumidity);
      Wire.write(0x3); // 0x3 for read 0x10 for write to registers
      Wire.write((byte)0x0);  // start at address 0x0 for humidity
      Wire.write(2);  // request 2 bytes data for humidity or 4 bytes for temperature+humidity
      Wire.endTransmission();
     
      Wire.requestFrom(I2CHumidity, 6); // Request 6 bytes
      for (int i=0;i<6;i++)
        if(Wire.available()) reply[i] = Wire.read();
      if (reply[0]==0x3 && reply[1]==0x2) // The response need to contain function (0x3) and length of data (0x2)
      {
        int crc=reply[5];
        crc<<=8;
        crc+=reply[4];
        if (crc == crc16(reply,4))
        {
          iHumidity=reply[2];
          iHumidity<<=8;
          iHumidity+=reply[3];
        }
      }
      Params.Humidity=iHumidity;
      if (Params.Humidity != OldParams.Humidity)
      {
        OldParams.Humidity = Params.Humidity;
        sprintf(buffer, "hum:%d", Params.Humidity);
        Publish(pub_buffer, buffer);
      }

      // Water Level
      for (int i = 0; i < WL_CHANNELS; i++)
      {
        unsigned long tempwl = 0;
        int iWL = 0;
        for (int a = 0; a < 20; a++)
        {
          if (i == 0)
          {
            Wire.requestFrom(I2CWaterLevel, 2);
            if (Wire.available())
            {
              iWL = Wire.read();
              iWL = iWL << 8;
              iWL += Wire.read();
            }
            tempwl += iWL;
            if (tempwl != 0 && pub_wl[0] == 'w') WLFound = true;
          }
          else
          {
            Wire.beginTransmission(I2CMultiWaterLevel);
            Wire.write(1); // Config Pointer
            byte addr = (0xb + i) << 4; // Select which channel to read
            addr += 0x03; // Programmable Gain
            Wire.write(addr);
            Wire.write(0x83);
            Wire.endTransmission();
            delay(10); // It takes 10ms for conversion to be completed
            Wire.beginTransmission(I2CMultiWaterLevel);
            Wire.write((uint8_t)0); // Convert Pointer
            Wire.endTransmission();
            Wire.requestFrom(I2CMultiWaterLevel, 2); // Request converted value
            if (Wire.available())
            {
              iWL = Wire.read();
              iWL = iWL << 8;
              iWL += Wire.read();
            }
            tempwl += iWL >> 4;
            if (tempwl != 0 && pub_multiwl[0] == 'w') MultiWLFound = true;
          }
        }
        tempwl = tempwl / 20;
        if (tempwl != 0)
        {
          Params.WL[i] = map(tempwl, WLMin[i], WLMax[i], 0, 100); // apply the calibration to the sensor reading
          Params.WL[i] = constrain(Params.WL[i], 0, 255);
        }
        if (WLCal[i])
        {
          if (i == 0)
          {
            if (pub_wl[0] == 'c')
              sprintf(buffer, "%s%d", pub_custom_wl, tempwl);
            else
              sprintf(buffer, "%sc:%d", pub_wl, tempwl);
          }
          else
          {
            if (pub_multiwl[0] == 'c')
              sprintf(buffer, "%s%d", pub_custom_multiwl, tempwl);
            else
              sprintf(buffer, "%sc:%d", pub_multiwl, tempwl);
          }
          Publish(pub_buffer, buffer);
        }
        else
        {
          if (Params.WL[i] != OldParams.WL[i])
          {
            OldParams.WL[i] = Params.WL[i];
            if (i == 0)
            {
              if (pub_wl[0] == 'c')
                sprintf(buffer, "%s%d", pub_wl, Params.WL[i]);
              else
                sprintf(buffer, "%s:%d:%d", pub_wl, i, Params.WL[i]);
            }
            else
            {
              if (pub_multiwl[0] == 'c')
                sprintf(buffer, "%s%d", pub_multiwl, Params.WL[i]);
              else
                sprintf(buffer, "%s:%d:%d", pub_multiwl, i, Params.WL[i]);
            }
            Publish(pub_buffer, buffer);
          }
        }
      }
      ds.reset();
      ds.select(addr1);
      ds.write(0x44, 0);
      ds.reset();
      ds.select(addr2);
      ds.write(0x44, 0);
    }
  }
}

void MQTTSubCallback(char* topic, byte* payload, unsigned int length) {

  boolean data_found = false;
  int payload_data = 0;
  byte data_index = 0;

  if (payload[0] == 'R' && payload[1] == 'O' && payload[2] == 'F' && payload[3] == 'F' && payload[5] == ':')
  {
    data_found = true;
    data_index = payload[4] - '0' - 1;
    for (byte a = 6; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    RelayMaskOffE[data_index] = payload_data;
  }
  else if (payload[0] == 'R' && payload[1] == 'O' && payload[2] == 'N' && payload[4] == ':')
  {
    data_found = true;
    data_index = payload[3] - '0' - 1;
    for (byte a = 5; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    RelayMaskOnE[data_index] = payload_data;
  }
  else if (payload[0] == 'R' && payload[2] == ':')
  {
    data_found = true;
    data_index = payload[1] - '0' - 1;
    for (byte a = 3; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    RelayDataE[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == 'E' && payload[5] == ':')
  {
    data_found = true;
    data_index = payload[4] - '0';
    for (byte a = 6; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    ExpansionChannel[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == 'E' && payload[5] == 'O' && payload[6] == ':')
  {
    data_found = true;
    data_index = payload[4] - '0';
    for (byte a = 7; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    ExpansionChannelOverride[data_index] = payload_data;
  }
  else if (payload[0] == 'O' && payload[1] == 'R' && payload[2] == 'P' && payload[3] == 'C' && payload[4] == ':' && ORPFound)
  {
    Serial.println(F("ORP calibration"));
    data_found = true;
    if (payload[5] == '0')
      ORPCal = false;
    else if (payload[5] == '1')
      ORPCal = true;
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      CalVal1 = payload_data;
    }
    else if (payload[5] == '3')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      memory_write_int(Mem_I_ORPMin, CalVal1);
      memory_write_int(Mem_I_ORPMax, payload_data);
      ORPMin = CalVal1;
      ORPMax = payload_data;
      ORPCal = false;
    }
  }
  else if (payload[0] == 'S' && payload[1] == 'A' && payload[2] == 'L' && payload[3] == 'C' && payload[4] == ':' && SalinityFound)
  {
    Serial.println(F("Sal calibration"));
    data_found = true;
    if (payload[5] == '0')
      SalCal = false;
    else if (payload[5] == '1')
      SalCal = true;
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      memory_write_int(Mem_I_SalMax, payload_data);
      SalMax = payload_data;
      SalCal = false;
    }
  }
  else if (payload[0] == 'P' && payload[1] == 'H' && payload[2] == 'E' && payload[3] == 'C' && payload[4] == ':' && PHExpFound)
  {
    Serial.println(F("PH Exp calibration"));
    data_found = true;
    if (payload[5] == '0')
      PHExpCal = false;
    else if (payload[5] == '1')
      PHExpCal = true;
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      CalVal1 = payload_data;
    }
    else if (payload[5] == '3')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      memory_write_int(Mem_I_PHExpMin, CalVal1);
      memory_write_int(Mem_I_PHExpMax, payload_data);
      PHExpMin = CalVal1;
      PHExpMax = payload_data;
      PHExpCal = false;
    }
  }
  else if (payload[0] == 'W' && payload[1] == 'L' && payload[3] == 'C' && payload[4] == ':' && (WLFound || MultiWLFound))
  {
    Serial.println(F("WL calibration"));
    data_found = true;
    data_index = payload[2] - '0';
    if (payload[5] == '0')
      WLCal[data_index] = false;
    else if (payload[5] == '1')
    {
      if (data_index == 0 && WLFound)
        WLCal[data_index] = true;
      if (data_index > 0 && MultiWLFound)
        WLCal[data_index] = true;
    }
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      CalVal1 = payload_data;
    }
    else if (payload[5] == '3')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      if (data_index == 0)
      {
        memory_write_int(Mem_I_WaterLevelMin, CalVal1);
        memory_write_int(Mem_I_WaterLevelMax, payload_data);
      }
      if (data_index > 0 && data_index < 5)
      {
        memory_write_int(Mem_I_WaterLevel1Min + (data_index * 2) - 2, CalVal1);
        memory_write_int(Mem_I_WaterLevel1Max + (data_index * 2) - 2, payload_data);
      }
      WLMin[data_index] = CalVal1;
      WLMax[data_index] = payload_data;
      WLCal[data_index] = false;
    }
  }
  else if (payload[0] == 'C' && payload[1] == 'E' && payload[2] == 'X' && payload[3] == 'P' && payload[5] == 'C' && payload[6] == ':')
  {
    Serial.println(F("Custom Exp calibration"));
    data_found = true;
    data_index = payload[4] - '0';
    if (payload[7] == '0')
    {
      if (pub_salinity[0] == 'c' && CustomExpansion[data_index] == CUSTOM_SALINITY) SalCal = false;
      if (pub_orp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_ORP) ORPCal = false;
      if (pub_phexp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_PHEXP) PHExpCal = false;
      if (pub_wl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_WL) WLCal[0] = false;
      for (int a = 1; a < WL_CHANNELS; a++)
        if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] >= CUSTOM_MULTI_WL1 && CustomExpansion[data_index] <= CUSTOM_MULTI_WL4) WLCal[a] = false;
    }
    else if (payload[7] == '1')
    {
      if (pub_salinity[0] == 'c' && CustomExpansion[data_index] == CUSTOM_SALINITY) SalCal = true;
      if (pub_orp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_ORP) ORPCal = true;
      if (pub_phexp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_PHEXP) PHExpCal = true;
      if (pub_wl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_WL) WLCal[0] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL1) WLCal[1] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL2) WLCal[2] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL3) WLCal[3] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL4) WLCal[4] = true;
    }
    else if (payload[7] == '2')
    {
      for (byte a = 9; a < length; a++)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
      CalVal1 = payload_data;
    }
    else if (payload[7] == '3')
    {
      for (byte a = 9; a < length; a++)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
      if (pub_salinity[0] == 'c')
      {
        memory_write_int(Mem_I_SalMax, payload_data);
        SalMax = payload_data;
        SalCal = false;
      }
      if (pub_orp[0] == 'c')
      {
        memory_write_int(Mem_I_ORPMin, CalVal1);
        memory_write_int(Mem_I_ORPMax, payload_data);
        ORPMin = CalVal1;
        ORPMax = payload_data;
        ORPCal = false;
      }
      if (pub_phexp[0] == 'c')
      {
        memory_write_int(Mem_I_PHExpMin, CalVal1);
        memory_write_int(Mem_I_PHExpMax, payload_data);
        PHExpMin = CalVal1;
        PHExpMax = payload_data;
        PHExpCal = false;
      }
      if (pub_wl[0] == 'c')
      {
        memory_write_int(Mem_I_WaterLevelMin, CalVal1);
        memory_write_int(Mem_I_WaterLevelMax, payload_data);
        WLMin[0] = CalVal1;
        WLMax[0] = payload_data;
        WLCal[0] = false;
      }
      for (int a = 1; a < WL_CHANNELS; a++)
        if (pub_multiwl[0] == 'c' && WLCal[a] == true)
        {
          memory_write_int(Mem_I_WaterLevel1Min + (a * 2) - 2, CalVal1);
          memory_write_int(Mem_I_WaterLevel1Max + (a * 2) - 2, payload_data);
          WLMin[a] = CalVal1;
          WLMax[a] = payload_data;
          WLCal[a] = false;
        }
    }
  }
  if (data_found)
  {
    blink_data_led(30);
    for (int a = 0; a < length; a++)
      Serial.write(payload[a]);
    Serial.println();
  }
}

const char* ip_to_str(const uint8_t* ipAddr)
{
  static char buf[16];
  sprintf(buf, "%d.%d.%d.%d", ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3]);
  return buf;
}

void ApplyCalibration(byte module, byte type)
{
  CustomExpansion[module - 1] = type;
  switch (type)
  {
    case CUSTOM_SALINITY:
      sprintf(pub_salinity, "cexp:%d:", module - 1);
      break;
    case CUSTOM_ORP:
      sprintf(pub_orp, "cexp:%d:", module - 1);
      break;
    case CUSTOM_PHEXP:
      sprintf(pub_phexp, "cexp:%d:", module - 1);
      break;
    case CUSTOM_WL:
      sprintf(pub_wl, "cexp:%d:", module - 1);
      sprintf(pub_custom_wl, "cexpc:%d:", module - 1);
      break;
    case CUSTOM_MULTI_WL1:
    case CUSTOM_MULTI_WL2:
    case CUSTOM_MULTI_WL3:
    case CUSTOM_MULTI_WL4:
      sprintf(pub_multiwl, "cexp:%d:", module - 1);
      sprintf(pub_custom_multiwl, "cexpc:%d:", module - 1);
      break;
    case CUSTOM_NONE:
      break;
  }
}

void blink_data_led(byte timer)
{
  digitalWrite(LED_RED, LOW);
  delay(timer);
  digitalWrite(LED_RED, HIGH);
}

void Publish(char* pub_buffer, char* buffer)
{
  MQTTClient.publish(pub_buffer, buffer);
  Serial.println(buffer);
  blink_data_led(50);
}

byte memory_read_byte(int address)
{
  byte rdata = 0xFF;
  Wire.beginTransmission(I2CEEPROM1);
  Wire.write((int)(address >> 8));   // MSB
  Wire.write((int)(address & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(I2CEEPROM1,1);
  if (Wire.available())
        rdata = Wire.read();
  return rdata;
}

void memory_write_byte(int address, const byte data)
{
  if (memory_read_int(address) != data)
  {
    Wire.beginTransmission(I2CEEPROM1);
    Wire.write((int)(address >> 8));   // MSB
    Wire.write((int)(address & 0xFF)); // LSB
    Wire.write(data);
    Wire.endTransmission();
    delay(10);
  }
}

int memory_read_int(int address)
{
  int rdata = 0xFFFF;
  Wire.beginTransmission(I2CEEPROM1);
  Wire.write((int)(address >> 8));   // MSB
  Wire.write((int)(address & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(I2CEEPROM1,2);
  if (Wire.available())
  {
        rdata = Wire.read();
        rdata += (Wire.read())<<8;
  }
  return rdata;
}

void memory_write_int(int address, const int data)
{
  if (memory_read_int(address) != data)
  {
    Wire.beginTransmission(I2CEEPROM1);
    Wire.write((int)(address >> 8));   // MSB
    Wire.write((int)(address & 0xFF)); // LSB
    Wire.write(data%256);
    Wire.write(data>>8);
    Wire.endTransmission();
    delay(10);
  }
}

void printWifiStatus() {
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

unsigned int crc16(int *ptr, byte len)
{
  unsigned int crc=0xFFFF;
  byte i;
  byte temp=0;
  int test;
  while(len--)
  {
    crc^=*ptr++;
    for(i=0;i<8;i++)
    {
      if(crc & 0x01)
      {
        crc>>=1;
        crc^=0xA001;
      }
      else
      {
        crc>>=1;
      }
    }
  }
  return crc;
}

void wdt_initialize()
{
  GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(4);
  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2) |
                      GCLK_GENCTRL_GENEN |
                      GCLK_GENCTRL_SRC_OSCULP32K |
                      GCLK_GENCTRL_DIVSEL;
  while (GCLK->STATUS.bit.SYNCBUSY);  // Syncronize write to GENCTRL reg.
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_WDT |
                      GCLK_CLKCTRL_CLKEN |
                      GCLK_CLKCTRL_GEN_GCLK2;
}

void wdt_enable()
{
  WDT->CTRL.reg &= ~WDT_CTRL_ENABLE;
  while (WDT->STATUS.bit.SYNCBUSY);  // Syncronize write to CTRL reg.
  WDT->CONFIG.reg = WDT_CONFIG_PER(0xA);  // 0xA = 8192 ms
  while (WDT->STATUS.bit.SYNCBUSY);  // Syncronize write to CONFIG reg.
  WDT->INTENCLR.reg |= WDT_INTENCLR_EW;
  WDT->CTRL.reg |= WDT_CTRL_ENABLE;
  while (WDT->STATUS.bit.SYNCBUSY);  // Syncronize write to CTRL reg.
}

void wdt_disable()
{
  WDT->CTRL.reg &= ~WDT_CTRL_ENABLE;
  while (WDT->STATUS.bit.SYNCBUSY);  // Syncronize write to CTRL reg.
}

void wdt_reset()
{
  WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;
  while (WDT->STATUS.bit.SYNCBUSY);  // Syncronize write to CLEAR reg.
}



// RA_STRING1=U2FsdGVkX1/i5QS5BGZK5riC7X8v1MxE964GYStk988=
// RA_STRING2=U2FsdGVkX19Lc9oWoOxRrp/GbHgXXsr2gDQc6rBkTKk=
// RA_STRING3=K2GVR



and I changed this section to:
Code: Select all
// Redirect expansion modules to another custom expansion field.
// This is only required if you have multiple modules of the same parameter.
// For example, if you have one Cloud module with an existing salinity module already and wants to add another Cloud module
// with anoter salinity module and report those readings as a Custom Expansion Module 1
// In this case you have to change the CloudCustomModule1 to CUSTOM_SALINITY.
// The values that can be entered are:
// CUSTOM_NONE   0
// CUSTOM_SALINITY   1
// CUSTOM_ORP   2
// CUSTOM_PHEXP   3
// CUSTOM_WL   4
// CUSTOM_MULTI_WL1   5
// CUSTOM_MULTI_WL2   6
// CUSTOM_MULTI_WL3   7
// CUSTOM_MULTI_WL4   8

#define CloudCustomModule1  CUSTOM_SALINITY
#define CloudCustomModule2  CUSTOM_NONE
#define CloudCustomModule3  CUSTOM_NONE
#define CloudCustomModule4  CUSTOM_NONE
#define CloudCustomModule5  CUSTOM_NONE
#define CloudCustomModule6  CUSTOM_NONE
#define CloudCustomModule7  CUSTOM_NONE
#define CloudCustomModule8  CUSTOM_NONE


but as I read the comments, don't think it was necessary.
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink

Posts: 12459
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Thu Mar 14, 2019 10:06 pm
Can you post a photo of the board?
I need to see the revision number.
Roberto.
User avatar
Posts: 86
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD
PostPosted: Fri Mar 15, 2019 2:20 am
The board is a Cloud Wifi Expansion v 1.4. I'll take a picture later today if needed.
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink

Posts: 12459
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Fri Mar 15, 2019 10:09 am
No need for photo.
This is the newest Could wifi hub and it doesn't work with the webwizard.
We will need to compile the code and upload it on your computer using the Arduino IDE.
It uses ESP8266 chip.

Start Arduino and open Preferences window.
Enter http://arduino.esp8266.com/stable/packa ... index.json into Additional Board Manager URLs field. You can add multiple URLs, separating them with commas.
Open Boards Manager from Tools > Board menu and find esp8266 platform.
Select the version you need from a drop-down box.
Click install button.

After it is installed, just to be sure, close Arduino and start it again to load everything it needs.
Then, go to menu Tools->Boards and you will see a bunch of ESP8266 boards. Pick the Adafruit HUZZAH ESP8266.
Try to compile this code:
Code: Select all
#include <FS.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266httpUpdate.h>
#include <WiFiManager.h>
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <Ticker.h>
#include <Wire.h>
#include <OneWire.h>
#include <CloudGlobals.h>

// ***********************************************************************
// Change fallback ports below
// Fallback ports will be turned on when cloud connection is lost
// Add each port separated by a |
// For example, if you would like for port 1 and port 5 of Relay Box 1 to be turned on when cloud connection is lost,
// you should add Port1Bit | Port5Bit
// It would look like this:
// #define Relay1FallBack Port1Bit | Port5Bit

#define Relay1FallBack 0
#define Relay2FallBack 0
#define Relay3FallBack 0
#define Relay4FallBack 0
#define Relay5FallBack 0
#define Relay6FallBack 0
#define Relay7FallBack 0
#define Relay8FallBack 0

// Redirect expansion modules to another custom expansion field.
// This is only required if you have multiple modules of the same parameter.
// For example, if you have one Cloud module with an existing salinity module already and wants to add another Cloud module
// with anoter salinity module and report those readings as a Custom Expansion Module 1
// In this case you have to change the CloudCustomModule1 to CUSTOM_SALINITY.
// The values that can be entered are:
// CUSTOM_NONE  0
// CUSTOM_SALINITY  1
// CUSTOM_ORP 2
// CUSTOM_PHEXP 3
// CUSTOM_WL  4
// CUSTOM_MULTI_WL1 5
// CUSTOM_MULTI_WL2 6
// CUSTOM_MULTI_WL3 7
// CUSTOM_MULTI_WL4 8

#define CloudCustomModule1  CUSTOM_NONE
#define CloudCustomModule2  CUSTOM_NONE
#define CloudCustomModule3  CUSTOM_NONE
#define CloudCustomModule4  CUSTOM_NONE
#define CloudCustomModule5  CUSTOM_NONE
#define CloudCustomModule6  CUSTOM_NONE
#define CloudCustomModule7  CUSTOM_NONE
#define CloudCustomModule8  CUSTOM_NONE

// Assign Temperature probes ID
// Only assign temperature probes IDs that you currently are not using in the head unit.
// If you have a total of more than 3 probes, make sure to add the following line on the setup section of the head unit code:
// ReefAngel.AddExtraTempProbes();
// For example, if you only have 1 probe connected to the head unit, assign IDs 2 and 3.
// If you have 2 probes in the head unit and 2 probes in the Cloud Wifi Hub, you must add the above line and you would assign
// IDs 3 and 4.
// Assign ID 0 to unused probes in the Hub.

byte TempProbeIDs[] = {4, 5};

// Do not change anything below
// ***********************************************************************
// solid green - factory reset
// blink green - connecting wifi
// blink blue - configuration required (SoftAP)
// blink magenta - connecting to cloud server
// solid cyan - connected to cloud server
// blinking cyan - transmitting/receiving data
// solid yellow - firmware update

#define LED_GREEN 2
#define LED_BLUE 0
#define LED_RED 16
#define RESET_ALL A0
#define INPUT1  12
#define INPUT2  13
#define TEMP_PIN  14

#define version "1.0.1"

#define MQTTServer "cloud.reefangel.com"

#define MQTTPORT 1883 // MQTT server port

WiFiManager wifiManager;
WiFiClient espClient;
PubSubClient CloudClient(espClient);
Ticker ticker;
OneWire ds(TEMP_PIN);

byte data[2];
byte addr[8];
byte addr1[8];
byte addr2[8];

boolean first_connection = true;
boolean shouldSaveConfig = false;
boolean updating = false;

unsigned long cloudmillis = millis();
unsigned long client_timeout = millis();
unsigned long serial_timeout = millis();

String currentLine = "";                // make a String to hold incoming data from the client

char mqtt_username[32];
char mqtt_password[32];

void APtick()
{
  //toggle state
  int state = digitalRead(LED_BLUE);  // get the current state of GPIO1 pin
  digitalWrite(LED_BLUE, !state);     // set pin to the opposite state
}

void Wifitick()
{
  //toggle state
  int state = digitalRead(LED_GREEN);  // get the current state of GPIO1 pin
  digitalWrite(LED_GREEN, !state);     // set pin to the opposite state
}

void Cloudtick()
{
  //toggle state
  int state = digitalRead(LED_BLUE);  // get the current state of GPIO1 pin
  digitalWrite(LED_RED, !state);     // set pin to the opposite state
  digitalWrite(LED_BLUE, !state);     // set pin to the opposite state
}

void Datatick()
{
  //toggle state
  int state = digitalRead(LED_BLUE);  // get the current state of GPIO1 pin
  digitalWrite(LED_GREEN, !state);     // set pin to the opposite state
  digitalWrite(LED_BLUE, !state);     // set pin to the opposite state
}

void LED_Color(int Red, int Green, int Blue)
{
  analogWrite(LED_RED, 1023 - Red);
  analogWrite(LED_GREEN, 1023 - Green);
  analogWrite(LED_BLUE, 1023 - Blue);
}

int memory_read_int(int address)
{
  return EEPROM.read(address);
}

void memory_write_int(int address, const int data)
{
  if (memory_read_int(address) != data)
  {
    EEPROM.write(address, data);
    EEPROM.commit();
  }
}

unsigned int crc16(int *ptr, byte len)
{
  unsigned int crc = 0xFFFF;
  byte i;
  byte temp = 0;
  int test;
  while (len--)
  {
    crc ^= *ptr++;
    for (i = 0; i < 8; i++)
    {
      if (crc & 0x01)
      {
        crc >>= 1;
        crc ^= 0xA001;
      }
      else
      {
        crc >>= 1;
      }
    }
  }
  return crc;
}

void blink_data_led(byte timer)
{
  digitalWrite(LED_RED, LOW);
  delay(timer);
  digitalWrite(LED_RED, HIGH);
}

void Publish(char* pub_buffer, char* buffer)
{
  CloudClient.publish(pub_buffer, buffer);
  Serial.print(pub_buffer);
  Serial.print(": ");
  Serial.println(buffer);
  blink_data_led(50);
}

void reconnect() {
  // Loop until we're reconnected
  if (!CloudClient.connected()) {
    cloudmillis = millis();
    //    Serial.print(F("Username: "));
    //    Serial.println(CLOUD_USERNAME);
    Serial.println("Connecting to cloud server...");
    // Attempt to connect
    //Serial.println(sub_buffer);
    if (CloudClient.connect(clientid, mqtt_username, mqtt_password)) {
      Serial.println("Connected");
      // Once connected, publish an announcement...
      Serial.print("Subscribing to ");
      Serial.println(sub_buffer);
      CloudClient.subscribe(sub_buffer);
      Publish(pub_buffer, "all:0");
      ticker.detach();
      LED_Color(0, 1023, 1023);

      //Serial.swap();
    } else {
      Serial.print("Failed, rc=");
      Serial.print(CloudClient.state());
      Serial.println(" try again in 30 seconds");
    }
  }
}

void ApplyCalibration(byte module, byte type)
{
  CustomExpansion[module - 1] = type;
  switch (type)
  {
    case CUSTOM_SALINITY:
      sprintf(pub_salinity, "cexp:%d:", module - 1);
      break;
    case CUSTOM_ORP:
      sprintf(pub_orp, "cexp:%d:", module - 1);
      break;
    case CUSTOM_PHEXP:
      sprintf(pub_phexp, "cexp:%d:", module - 1);
      break;
    case CUSTOM_WL:
      sprintf(pub_wl, "cexp:%d:", module - 1);
      sprintf(pub_custom_wl, "cexpc:%d:", module - 1);
      break;
    case CUSTOM_MULTI_WL1:
    case CUSTOM_MULTI_WL2:
    case CUSTOM_MULTI_WL3:
    case CUSTOM_MULTI_WL4:
      sprintf(pub_multiwl, "cexp:%d:", module - 1);
      sprintf(pub_custom_multiwl, "cexpc:%d:", module - 1);
      break;
    case CUSTOM_NONE:
      break;
  }
}

void saveConfigCallback () {
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

void configModeCallback (WiFiManager *myWiFiManager) {
  LED_Color(0, 0, 0);
  ticker.detach();
  Serial.println("Entered config mode");
  WiFi.softAPIP();
  ticker.attach(0.5, APtick);
}

void WifiCheckCallback () {
  WiFi.softAPdisconnect(true);
  LED_Color(0, 0, 0);
  ticker.detach();
  Serial.println("Checking Wifi Credentials");
  ticker.attach(0.5, Wifitick);
}

void callback(char* topic, byte* payload, unsigned int length) {

  boolean data_found = false;
  int payload_data = 0;
  byte data_index = 0;

  Serial.print("cloud:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  if (payload[0] == 'R' && payload[1] == 'O' && payload[2] == 'F' && payload[3] == 'F' && payload[5] == ':')
  {
    data_found = true;
    data_index = payload[4] - '0' - 1;
    for (byte a = 6; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    RelayMaskOffE[data_index] = payload_data;
  }
  else if (payload[0] == 'R' && payload[1] == 'O' && payload[2] == 'N' && payload[4] == ':')
  {
    data_found = true;
    data_index = payload[3] - '0' - 1;
    for (byte a = 5; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    RelayMaskOnE[data_index] = payload_data;
  }
  else if (payload[0] == 'R' && payload[2] == ':')
  {
    data_found = true;
    data_index = payload[1] - '0' - 1;
    for (byte a = 3; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    RelayDataE[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == 'E' && payload[5] == ':')
  {
    data_found = true;
    data_index = payload[4] - '0';
    for (byte a = 6; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    ExpansionChannel[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == 'E' && payload[5] == 'O' && payload[6] == ':')
  {
    data_found = true;
    data_index = payload[4] - '0';
    for (byte a = 7; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    ExpansionChannelOverride[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == '1' && payload[4] == '6' && payload[5] == 'E' && payload[8] == ':')
  {
    data_found = true;
    data_index = (payload[6] - '0') * 10;
    data_index += (payload[7] - '0');
    for (byte a = 9; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    Expansion16Channel[data_index] = payload_data;
  }
  else if (payload[0] == 'P' && payload[1] == 'W' && payload[2] == 'M' && payload[3] == '1' && payload[4] == '6' && payload[5] == 'E' && payload[6] == 'O' && payload[9] == ':')
  {
    data_found = true;
    data_index = (payload[7] - '0') * 10;
    data_index += (payload[8] - '0');
    for (byte a = 10; a < length; a++)
    {
      if (payload[a] != 10 && payload[a] != 13)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
    }
    Expansion16ChannelOverride[data_index] = payload_data;
  }
  else if (payload[0] == 'O' && payload[1] == 'R' && payload[2] == 'P' && payload[3] == 'C' && payload[4] == ':' && ORPFound)
  {
    Serial.println(F("ORP calibration"));
    data_found = true;
    if (payload[5] == '0')
      ORPCal = false;
    else if (payload[5] == '1')
      ORPCal = true;
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      CalVal1 = payload_data;
    }
    else if (payload[5] == '3')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      memory_write_int(Mem_I_ORPMin, CalVal1);
      memory_write_int(Mem_I_ORPMax, payload_data);
      ORPMin = CalVal1;
      ORPMax = payload_data;
      ORPCal = false;
    }
  }
  else if (payload[0] == 'S' && payload[1] == 'A' && payload[2] == 'L' && payload[3] == 'C' && payload[4] == ':' && SalinityFound)
  {
    Serial.println(F("Sal calibration"));
    data_found = true;
    if (payload[5] == '0')
      SalCal = false;
    else if (payload[5] == '1')
      SalCal = true;
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      memory_write_int(Mem_I_SalMax, payload_data);
      SalMax = payload_data;
      SalCal = false;
    }
  }
  else if (payload[0] == 'P' && payload[1] == 'H' && payload[2] == 'E' && payload[3] == 'C' && payload[4] == ':' && PHExpFound)
  {
    Serial.println(F("PH Exp calibration"));
    data_found = true;
    if (payload[5] == '0')
      PHExpCal = false;
    else if (payload[5] == '1')
      PHExpCal = true;
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      CalVal1 = payload_data;
    }
    else if (payload[5] == '3')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      memory_write_int(Mem_I_PHExpMin, CalVal1);
      memory_write_int(Mem_I_PHExpMax, payload_data);
      PHExpMin = CalVal1;
      PHExpMax = payload_data;
      PHExpCal = false;
    }
  }
  else if (payload[0] == 'W' && payload[1] == 'L' && payload[3] == 'C' && payload[4] == ':' && (WLFound || MultiWLFound))
  {
    Serial.println(F("WL calibration"));
    data_found = true;
    data_index = payload[2] - '0';
    if (payload[5] == '0')
      WLCal[data_index] = false;
    else if (payload[5] == '1')
    {
      if (data_index == 0 && WLFound)
        WLCal[data_index] = true;
      if (data_index > 0 && MultiWLFound)
        WLCal[data_index] = true;
    }
    else if (payload[5] == '2')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      CalVal1 = payload_data;
    }
    else if (payload[5] == '3')
    {
      for (byte a = 7; a < length; a++)
      {
        if (payload[a] != 10 && payload[a] != 13)
        {
          payload_data *= 10;
          payload_data += payload[a] - '0';
        }
      }
      if (data_index == 0)
      {
        memory_write_int(Mem_I_WaterLevelMin, CalVal1);
        memory_write_int(Mem_I_WaterLevelMax, payload_data);
      }
      if (data_index > 0 && data_index < 5)
      {
        memory_write_int(Mem_I_WaterLevel1Min + (data_index * 2) - 2, CalVal1);
        memory_write_int(Mem_I_WaterLevel1Max + (data_index * 2) - 2, payload_data);
      }
      WLMin[data_index] = CalVal1;
      WLMax[data_index] = payload_data;
      WLCal[data_index] = false;
    }
  }
  else if (payload[0] == 'C' && payload[1] == 'E' && payload[2] == 'X' && payload[3] == 'P' && payload[5] == 'C' && payload[6] == ':')
  {
    Serial.println(F("Custom Exp calibration"));
    data_found = true;
    data_index = payload[4] - '0';
    if (payload[7] == '0')
    {
      if (pub_salinity[0] == 'c' && CustomExpansion[data_index] == CUSTOM_SALINITY) SalCal = false;
      if (pub_orp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_ORP) ORPCal = false;
      if (pub_phexp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_PHEXP) PHExpCal = false;
      if (pub_wl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_WL) WLCal[0] = false;
      for (int a = 1; a < WL_CHANNELS; a++)
        if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] >= CUSTOM_MULTI_WL1 && CustomExpansion[data_index] <= CUSTOM_MULTI_WL4) WLCal[a] = false;
    }
    else if (payload[7] == '1')
    {
      if (pub_salinity[0] == 'c' && CustomExpansion[data_index] == CUSTOM_SALINITY) SalCal = true;
      if (pub_orp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_ORP) ORPCal = true;
      if (pub_phexp[0] == 'c' && CustomExpansion[data_index] == CUSTOM_PHEXP) PHExpCal = true;
      if (pub_wl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_WL) WLCal[0] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL1) WLCal[1] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL2) WLCal[2] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL3) WLCal[3] = true;
      if (pub_multiwl[0] == 'c' && CustomExpansion[data_index] == CUSTOM_MULTI_WL4) WLCal[4] = true;
    }
    else if (payload[7] == '2')
    {
      for (byte a = 9; a < length; a++)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
      CalVal1 = payload_data;
    }
    else if (payload[7] == '3')
    {
      for (byte a = 9; a < length; a++)
      {
        payload_data *= 10;
        payload_data += payload[a] - '0';
      }
      if (pub_salinity[0] == 'c')
      {
        memory_write_int(Mem_I_SalMax, payload_data);
        SalMax = payload_data;
        SalCal = false;
      }
      if (pub_orp[0] == 'c')
      {
        memory_write_int(Mem_I_ORPMin, CalVal1);
        memory_write_int(Mem_I_ORPMax, payload_data);
        ORPMin = CalVal1;
        ORPMax = payload_data;
        ORPCal = false;
      }
      if (pub_phexp[0] == 'c')
      {
        memory_write_int(Mem_I_PHExpMin, CalVal1);
        memory_write_int(Mem_I_PHExpMax, payload_data);
        PHExpMin = CalVal1;
        PHExpMax = payload_data;
        PHExpCal = false;
      }
      if (pub_wl[0] == 'c')
      {
        memory_write_int(Mem_I_WaterLevelMin, CalVal1);
        memory_write_int(Mem_I_WaterLevelMax, payload_data);
        WLMin[0] = CalVal1;
        WLMax[0] = payload_data;
        WLCal[0] = false;
      }
      for (int a = 1; a < WL_CHANNELS; a++)
        if (pub_multiwl[0] == 'c' && WLCal[a] == true)
        {
          memory_write_int(Mem_I_WaterLevel1Min + (a * 2) - 2, CalVal1);
          memory_write_int(Mem_I_WaterLevel1Max + (a * 2) - 2, payload_data);
          WLMin[a] = CalVal1;
          WLMax[a] = payload_data;
          WLCal[a] = false;
        }
    }
  }
  if (data_found)
  {
    blink_data_led(30);
    for (int a = 0; a < length; a++)
      Serial.write(payload[a]);
    Serial.println();
  }
}

void setup() {
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  pinMode(LED_RED, OUTPUT);
  pinMode(INPUT1, INPUT_PULLUP);
  pinMode(INPUT2, INPUT_PULLUP);
  digitalWrite(LED_GREEN, LOW);
  digitalWrite(LED_BLUE, HIGH);
  digitalWrite(LED_RED, HIGH);
  randomSeed(analogRead(0));
  wifi_station_set_hostname( "ReefAngelCloudHub" );
  Serial.begin(57600);
  Serial.setRxBufferSize(2048);
  EEPROM.begin(512);
  Wire.begin();

  wifiManager.setDebugOutput(true);

  Serial.println("");
  Serial.print("Current version: ");
  Serial.println(version);

  SalinityFound = false;
  ORPFound = false;
  PHExpFound = false;
  WLFound = false;
  MultiWLFound = false;
  HumidityFound = false;

  sprintf(pub_salinity, "sal");
  sprintf(pub_orp, "orp");
  sprintf(pub_phexp, "phe");
  sprintf(pub_wl, "wl");
  sprintf(pub_multiwl, "wl");
  sprintf(pub_humidity, "hum");

  // Temperature
  byte count = 0;
  while (ds.search(addr))
  {
    if (addr[0] == 0x28)
    {
      count++;
      if (count == 1) memcpy(addr1, addr, 8);
      if (count == 2) memcpy(addr2, addr, 8);
    }
  }
  ds.reset_search();
  Serial.print(count);
  Serial.println(" temperature probe(s) found");

  // Relay
  for ( byte EID = 0; EID < MAX_RELAY_EXPANSION_MODULES; EID++ )
  {
    RelayDataE[EID] = 0;
    RelayMaskOnE[EID] = 0;
    RelayMaskOffE[EID] = 0xff;
  }
  RelayFallBackE[0] = Relay1FallBack;
  RelayFallBackE[1] = Relay2FallBack;
  RelayFallBackE[2] = Relay3FallBack;
  RelayFallBackE[3] = Relay4FallBack;
  RelayFallBackE[4] = Relay5FallBack;
  RelayFallBackE[5] = Relay6FallBack;
  RelayFallBackE[6] = Relay7FallBack;
  RelayFallBackE[7] = Relay8FallBack;

  // Dimming
  lastcrc = -1;
  for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ )
  {
    ExpansionChannel[a] = 0;
    ExpansionChannelOverride[a] = 255;
  }

  // 16 Channel Dimming
  lastcrc16 = -1;
  for ( byte a = 0; a < PWM16_EXPANSION_CHANNELS; a++ )
  {
    Expansion16Channel[a] = 0;
    Expansion16ChannelOverride[a] = 255;
  }

  // IO
  Params.IO = 63;
  OldParams.IO = 63;

  // Leak
  Params.Leak = 0;
  OldParams.Leak = 0;

  // ORP
  Params.ORP = 0;
  OldParams.ORP = 0;
  ORPCal = false;
  ORPMin = memory_read_int(Mem_I_ORPMin);
  if (ORPMin == 65535) ORPMin = 0;
  ORPMax = memory_read_int(Mem_I_ORPMax);

  // Salinity
  Params.Salinity = 0;
  OldParams.Salinity = 0;
  SalCal = false;
  SalMax = memory_read_int(Mem_I_SalMax);

  // pH Exp
  Params.PHExp = 0;
  OldParams.PHExp = 0;
  PHExpCal = false;
  PHExpMin = memory_read_int(Mem_I_PHExpMin);
  if (PHExpMin == 65535) PHExpMin = 0;
  PHExpMax = memory_read_int(Mem_I_PHExpMax);

  // Humidity
  Params.Humidity = 0;
  OldParams.Humidity = 0;

  // Water Level
  for (int a = 0; a < WL_CHANNELS; a++)
  {
    Params.WL[a] = 0;
    OldParams.WL[a] = 0;
    WLCal[a] = false;
  }
  WLMin[0] = memory_read_int(Mem_I_WaterLevelMin);
  WLMax[0] = memory_read_int(Mem_I_WaterLevelMax);
  WLMin[1] = memory_read_int(Mem_I_WaterLevel1Min);
  WLMax[1] = memory_read_int(Mem_I_WaterLevel1Max);
  WLMin[2] = memory_read_int(Mem_I_WaterLevel2Min);
  WLMax[2] = memory_read_int(Mem_I_WaterLevel2Max);
  WLMin[3] = memory_read_int(Mem_I_WaterLevel3Min);
  WLMax[3] = memory_read_int(Mem_I_WaterLevel3Max);
  WLMin[4] = memory_read_int(Mem_I_WaterLevel4Min);
  WLMax[4] = memory_read_int(Mem_I_WaterLevel4Max);

  for (int a = 0; a < 5; a++)
  {
    if (WLMin[a] == 65535) WLMin[a] = 0;
  }
  ApplyCalibration(1, CloudCustomModule1);
  ApplyCalibration(2, CloudCustomModule2);
  ApplyCalibration(3, CloudCustomModule3);
  ApplyCalibration(4, CloudCustomModule4);
  ApplyCalibration(5, CloudCustomModule5);
  ApplyCalibration(6, CloudCustomModule6);
  ApplyCalibration(7, CloudCustomModule7);
  ApplyCalibration(8, CloudCustomModule8);

  if (analogRead(RESET_ALL) < 50)
  {
    //    updating=true;
    Serial.println("Resetting");
    EEPROM.write(128, 0);
    EEPROM.commit();
    ESP.reset();
    while (1);
  }

  wifiManager.setVersion(version);
  if (EEPROM.read(128) != 1)
  {
    wifiManager.resetSettings();
    SPIFFS.format();
    EEPROM.write(128, 1);
    EEPROM.commit();
  }

  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
          Serial.println("\nparsed json");

          strcpy(mqtt_username, json["mqtt_username"]);
          strcpy(mqtt_password, json["mqtt_password"]);

        } else {
          Serial.println("failed to load json config");
        }
      }
    }
  } else {
    Serial.println("failed to mount FS");
  }

  WiFiManagerParameter custom_mqtt_username("Cloud Username", "Cloud Username", mqtt_username, 40);
  WiFiManagerParameter custom_mqtt_password("Cloud Password", "Cloud Password", mqtt_password, 40);
  wifiManager.addParameter(&custom_mqtt_username);
  wifiManager.addParameter(&custom_mqtt_password);
  wifiManager.setSaveConfigCallback(saveConfigCallback);
  wifiManager.setAPCallback(configModeCallback);
  wifiManager.setCheckWifiCallback(WifiCheckCallback);

  LED_Color(0, 0, 0);
  ticker.attach(0.5, Wifitick);
  wifiManager.autoConnect("ReefAngelCloudHub");
  ticker.detach();
  LED_Color(900, 0, 1023);

  CloudClient.setServer(MQTTServer, MQTTPORT);
  CloudClient.setCallback(callback);

  strcpy(mqtt_username, custom_mqtt_username.getValue());
  strcpy(mqtt_password, custom_mqtt_password.getValue());
  Serial.print("username: ");
  Serial.println(mqtt_username);
  //  Serial.print("password: ");
  //  Serial.println(mqtt_password);
  sprintf(clientid, "%s%02d", mqtt_username, random(10000));
  sprintf(pub_buffer, "%s/in", mqtt_username);
  sprintf(sub_buffer, "%s/out/#", mqtt_username);
  Serial.println("Start");

  if (shouldSaveConfig) {
    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["mqtt_username"] = mqtt_username;
    json["mqtt_password"] = mqtt_password;

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }

    json.printTo(Serial);
    Serial.println("");
    json.printTo(configFile);
    configFile.close();
    //end save
  }

  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

}

void loop() {
  if ((analogRead(RESET_ALL) < 50) && !updating)
  {
    if (WiFi.status() == WL_CONNECTED)
    {
      updating = true;
      ticker.detach();
      LED_Color(1023, 900, 0);
      Serial.println("Updating...");
      ESPhttpUpdate.update("forum.reefangel.com", 80, "/firmware/CloudWifiESP8266Hub.ino.bin");
    }
    else
    {
      Serial.println("Resetting");
      EEPROM.write(128, 0);
      EEPROM.commit();
      ESP.reset();
      while (1);
    }
  }
  if (!CloudClient.connected() && (((millis() - cloudmillis) > 30000) || first_connection)) {
    first_connection = false;
    LED_Color(0, 0, 0);
    ticker.detach();
    ticker.attach(0.5, Cloudtick);
    reconnect();
  }
  CloudClient.loop();

  // Relay
  for ( byte EID = 0; EID < MAX_RELAY_EXPANSION_MODULES; EID++ )
  {
    byte TempRelay = RelayDataE[EID];
    TempRelay &= RelayMaskOffE[EID];
    TempRelay |= RelayMaskOnE[EID];
    if (!CloudClient.connected())
      TempRelay = RelayFallBackE[EID];
    Wire.beginTransmission(I2CExpModule + EID);
    Wire.write(~TempRelay);  // MSB
    Wire.endTransmission();
  }

  // Dimming
  byte thiscrc = 0;
  for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ )
  {
    thiscrc += ExpansionChannel[a] * (a + 1);
    thiscrc += ExpansionChannelOverride[a] * (a + 1);
  }
  if (millis() % 60000 < 200) lastcrc = -1;
  if (lastcrc != thiscrc || millis() < 5000)
  {
    lastcrc = thiscrc;
    // setup PCA9685 for data receive
    // we need this to make sure it will work if connected ofter controller is booted, so we need to send it all the time.
    Wire.beginTransmission(I2CPWM_PCA9685);
    Wire.write((uint8_t)0);
    Wire.write(0xa1);
    Wire.endTransmission();
    for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ )
    {
      int data;
      if (ExpansionChannelOverride[a] <= 100)
        data = ExpansionChannelOverride[a] * 40.96;
      else
        data = ExpansionChannel[a] * 40.96;
      Wire.beginTransmission(I2CPWM_PCA9685);
      Wire.write(0x8 + (4 * a));
      Wire.write(data & 0xff);
      Wire.write(data >> 8);
      Wire.endTransmission();
    }
  }

  // 16 Channel Dimming
  int thiscrc16 = 0;
  for ( byte a = 0; a < PWM16_EXPANSION_CHANNELS; a++ )
  {
    thiscrc16 += Expansion16Channel[a] * (a + 1);
    thiscrc16 += Expansion16ChannelOverride[a] * (a + 1);
  }
  if (millis() % 60000 < 200) lastcrc16 = -1;
  if (lastcrc16 != thiscrc16 || millis() < 5000)
  {
    lastcrc16 = thiscrc16;
    // setup PCA9685 for data receive
    // we need this to make sure it will work if connected ofter controller is booted, so we need to send it all the time.
    Wire.beginTransmission(I2CPWM_16CH_PCA9685);
    Wire.write((uint8_t)0);
    Wire.write(0xa1);
    Wire.endTransmission();
    for ( byte a = 0; a < PWM16_EXPANSION_CHANNELS; a++ )
    {
      int data;
      if (Expansion16ChannelOverride[a] <= 100)
        data = Expansion16ChannelOverride[a];
      else
        data = Expansion16Channel[a];
      Wire.beginTransmission(I2CPWM_16CH_PCA9685);
      Wire.write(0x8 + (4 * a));
      Wire.write(data & 0xff);
      Wire.write(data >> 8);
      Wire.endTransmission();
    }
  }

  if (CloudClient.connected())
  {
    // IO
    Params.IO = 63;
    Wire.requestFrom(I2CIO_PCF8574, 1);
    if (Wire.available())
      Params.IO = Wire.read();
    if (digitalRead(INPUT1) == HIGH) Params.IO += 64;
    if (digitalRead(INPUT2) == HIGH) Params.IO += 128;
    if (Params.IO != OldParams.IO)
    {
      OldParams.IO = Params.IO;
      sprintf(buffer, "io:%d", Params.IO);
      Publish(pub_buffer, buffer);
    }

    // Leak
    int iLeak = 0;
    Wire.requestFrom(I2CLeak, 2);
    if (Wire.available())
    {
      iLeak = Wire.read();
      iLeak = iLeak << 8;
      iLeak += Wire.read();
      Params.Leak = iLeak > 2000;
    }
    if (Params.Leak != OldParams.Leak)
    {
      OldParams.Leak = Params.Leak;
      sprintf(buffer, "leak:%d", Params.Leak);
      Publish(pub_buffer, buffer);
    }

    if (millis() - Paramsmillis > 1000)
    {
      Paramsmillis = millis();

      // Temperature
      if (addr1[0] != 0)
      {
        ds.reset();
        ds.select(addr1);
        ds.write(0xBE);         // Read Scratchpad
        for (byte i = 0; i < 2; i++)
        {
          data[i] = ds.read();
        }
        Params.Temp[1] = (data[1] << 8) + data[0]; //take the two bytes from the response relating to temperature
        Params.Temp[1] = Params.Temp[1] / 1.6;
        if (Params.Temp[1] == 0) Params.Temp[1] = 0;
        if (Params.Temp[1] > 850) Params.Temp[1] = 0;
        Params.Temp[1] = Params.Temp[1] * 1.8 + 320;
        if (Params.Temp[1] != OldParams.Temp[1])
        {
          OldParams.Temp[1] = Params.Temp[1];
          sprintf(buffer, "t:%d:%d", TempProbeIDs[0], Params.Temp[1]);
          if (TempProbeIDs[0] != 0) Publish(pub_buffer, buffer);
        }
      }
      if (addr2[0] != 0)
      {
        ds.reset();
        ds.select(addr2);
        ds.write(0xBE);         // Read Scratchpad
        for (byte i = 0; i < 2; i++)
        {
          data[i] = ds.read();
        }
        Params.Temp[2] = (data[1] << 8) + data[0]; //take the two bytes from the response relating to temperature
        Params.Temp[2] = Params.Temp[2] / 1.6;
        if (Params.Temp[2] == 0) Params.Temp[2] = 0;
        if (Params.Temp[2] > 850) Params.Temp[2] = 0;
        Params.Temp[2] = Params.Temp[2] * 1.8 + 320;
        if (Params.Temp[2] != OldParams.Temp[2])
        {
          OldParams.Temp[2] = Params.Temp[2];
          sprintf(buffer, "t:%d:%d", TempProbeIDs[1], Params.Temp[2]);
          if (TempProbeIDs[1] != 0) Publish(pub_buffer, buffer);
        }
      }

      // ORP
      unsigned long temporp = 0;
      int iORP = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CORP, 2);
        if (Wire.available())
        {
          iORP = Wire.read();
          iORP = iORP << 8;
          iORP += Wire.read();
        }
        temporp += iORP;
      }
      temporp = temporp / 20;
      if (temporp != 0)
      {
        Params.ORP = map(temporp, ORPMin, ORPMax, 0, 470); // apply the calibration to the sensor reading
        Params.ORP = constrain(Params.ORP, 0, 550);
        if (pub_orp[0] == 'o') ORPFound = true;
      }
      if (ORPCal)
      {
        sprintf(buffer, "%sc:%d", pub_orp, temporp);
        Publish(pub_buffer, buffer);
      }
      else
      {
        if (Params.ORP != OldParams.ORP)
        {
          OldParams.ORP = Params.ORP;
          sprintf(buffer, "%s:%d", pub_orp, Params.ORP);
          Publish(pub_buffer, buffer);
        }
      }

      // Salinity
      unsigned long tempsal = 0;
      int iSAL = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CSalinity, 2);
        if (Wire.available())
        {
          iSAL = Wire.read();
          iSAL = iSAL << 8;
          iSAL += Wire.read();
        }
        tempsal += iSAL;
      }
      tempsal = tempsal / 20;
      if (tempsal != 0)
      {
        Params.Salinity = map(tempsal, 0, SalMax, 60, 350); // apply the calibration to the sensor reading
        if (pub_salinity[0] == 's') SalinityFound = true;
      }
      if (SalCal)
      {
        sprintf(buffer, "%sc:%d", pub_salinity, tempsal);
        Publish(pub_buffer, buffer);
      }
      else
      {
        if (Params.Salinity != OldParams.Salinity)
        {
          OldParams.Salinity = Params.Salinity;
          sprintf(buffer, "%s:%d", pub_salinity, Params.Salinity);
          Publish(pub_buffer, buffer);
        }
      }

      // pH Exp
      unsigned long tempphexp = 0;
      int iPHExp = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CPH, 2);
        if (Wire.available())
        {
          iPHExp = Wire.read();
          iPHExp = iPHExp << 8;
          iPHExp += Wire.read();
        }
        tempphexp += iPHExp;
      }
      tempphexp = tempphexp / 20;
      if (tempphexp != 0)
      {
        Params.PHExp = map(tempphexp, PHExpMin, PHExpMax, 700, 1000); // apply the calibration to the sensor reading
        Params.PHExp = constrain(Params.PHExp, 100, 1400);
        if (pub_phexp[0] == 'p') PHExpFound = true;
      }
      if (PHExpCal)
      {
        sprintf(buffer, "%sc:%d", pub_phexp, tempphexp);
        Publish(pub_buffer, buffer);
      }
      else
      {
        if (Params.PHExp != OldParams.PHExp)
        {
          OldParams.PHExp = Params.PHExp;
          sprintf(buffer, "%s:%d", pub_phexp, Params.PHExp);
          Publish(pub_buffer, buffer);
        }
      }

      // PAR
      unsigned long temppar = 0;
      int iPAR = 0;
      for (int a = 0; a < 20; a++)
      {
        Wire.requestFrom(I2CPAR, 2);
        if (Wire.available())
        {
          iPAR = Wire.read();
          iPAR = iPAR << 8;
          iPAR += Wire.read();
        }
        temppar += iPAR;
      }
      temppar = temppar / 20;
      if (temppar != 0)
      {
        temppar *= 5000; // apply the calibration to the sensor reading
        temppar /= 8192;
        Params.PAR = temppar;
      }
      if (Params.PAR != OldParams.PAR)
      {
        OldParams.PAR = Params.PAR;
        sprintf(buffer, "par:%d", Params.PAR);
        Publish(pub_buffer, buffer);
      }

      // Humidity
      int iHumidity = 0;
      int reply[10];

      Wire.beginTransmission(I2CHumidity);
      Wire.endTransmission();  // For some reason, it needs this to work??? Bug with sensor??
      Wire.beginTransmission(I2CHumidity);
      Wire.write(0x3); // 0x3 for read 0x10 for write to registers
      Wire.write((byte)0x0);  // start at address 0x0 for humidity
      Wire.write(2);  // request 2 bytes data for humidity or 4 bytes for temperature+humidity
      Wire.endTransmission();

      Wire.requestFrom(I2CHumidity, 6); // Request 6 bytes
      for (int i = 0; i < 6; i++)
        if (Wire.available()) reply[i] = Wire.read();
      if (reply[0] == 0x3 && reply[1] == 0x2) // The response need to contain function (0x3) and length of data (0x2)
      {
        int crc = reply[5];
        crc <<= 8;
        crc += reply[4];
        if (crc == crc16(reply, 4))
        {
          iHumidity = reply[2];
          iHumidity <<= 8;
          iHumidity += reply[3];
        }
      }
      Params.Humidity = iHumidity;
      if (Params.Humidity != OldParams.Humidity)
      {
        OldParams.Humidity = Params.Humidity;
        sprintf(buffer, "hum:%d", Params.Humidity);
        Publish(pub_buffer, buffer);
      }

      // Water Level
      for (int i = 0; i < WL_CHANNELS; i++)
      {
        unsigned long tempwl = 0;
        int iWL = 0;
        for (int a = 0; a < 20; a++)
        {
          if (i == 0)
          {
            Wire.requestFrom(I2CWaterLevel, 2);
            if (Wire.available())
            {
              iWL = Wire.read();
              iWL = iWL << 8;
              iWL += Wire.read();
            }
            tempwl += iWL;
            if (tempwl != 0 && pub_wl[0] == 'w') WLFound = true;
          }
          else
          {
            Wire.beginTransmission(I2CMultiWaterLevel);
            Wire.write(1); // Config Pointer
            byte addr = (0xb + i) << 4; // Select which channel to read
            addr += 0x03; // Programmable Gain
            Wire.write(addr);
            Wire.write(0x83);
            Wire.endTransmission();
            delay(10); // It takes 10ms for conversion to be completed
            Wire.beginTransmission(I2CMultiWaterLevel);
            Wire.write((uint8_t)0); // Convert Pointer
            Wire.endTransmission();
            Wire.requestFrom(I2CMultiWaterLevel, 2); // Request converted value
            if (Wire.available())
            {
              iWL = Wire.read();
              iWL = iWL << 8;
              iWL += Wire.read();
            }
            tempwl += iWL >> 4;
            if (tempwl != 0 && pub_multiwl[0] == 'w') MultiWLFound = true;
          }
        }
        tempwl = tempwl / 20;
        if (tempwl != 0)
        {
          Params.WL[i] = map(tempwl, WLMin[i], WLMax[i], 0, 100); // apply the calibration to the sensor reading
          Params.WL[i] = constrain(Params.WL[i], 0, 255);
        }
        if (WLCal[i])
        {
          if (i == 0)
          {
            if (pub_wl[0] == 'c')
              sprintf(buffer, "%s%d", pub_custom_wl, tempwl);
            else
              sprintf(buffer, "%sc:%d", pub_wl, tempwl);
          }
          else
          {
            if (pub_multiwl[0] == 'c')
              sprintf(buffer, "%s%d", pub_custom_multiwl, tempwl);
            else
              sprintf(buffer, "%sc:%d", pub_multiwl, tempwl);
          }
          Publish(pub_buffer, buffer);
        }
        else
        {
          if (Params.WL[i] != OldParams.WL[i])
          {
            OldParams.WL[i] = Params.WL[i];
            if (i == 0)
            {
              if (pub_wl[0] == 'c')
                sprintf(buffer, "%s%d", pub_wl, Params.WL[i]);
              else
                sprintf(buffer, "%s:%d:%d", pub_wl, i, Params.WL[i]);
            }
            else
            {
              if (pub_multiwl[0] == 'c')
                sprintf(buffer, "%s%d", pub_multiwl, Params.WL[i]);
              else
                sprintf(buffer, "%s:%d:%d", pub_multiwl, i, Params.WL[i]);
            }
            Publish(pub_buffer, buffer);
          }
        }
      }
      ds.reset();
      ds.select(addr1);
      ds.write(0x44, 0);
      ds.reset();
      ds.select(addr2);
      ds.write(0x44, 0);
    }
  }
}

This is the code we previously loaded with the 16ch Dimming feature enabled.
Roberto.
User avatar
Posts: 86
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD
PostPosted: Fri Mar 15, 2019 6:57 pm
Open Boards Manager from Tools > Board menu and find esp8266 platform.
Select the version you need from a drop-down box.
Click install button.

After it is installed, just to be sure, close Arduino and start it again to load everything it needs.
Then, go to menu Tools->Boards and you will see a bunch of ESP8266 boards. Pick the Adafruit HUZZAH ESP8266.
Try to compile this code:


Having problems with the version. On the esp8266 select version drop down, I see the following:

1.6.5 and 2.0 thru 2.5.0 versions. When I select 2.4 and 2.5 versions, the board closest available is Adafruit feather HUZZAH esp8266. The others that I tried 1.6.5 and 2.0.0 version have the Adfruit HUZZAH ESP8266 board but in all cases, the code would not compile with errors.
Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink

Posts: 12459
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Fri Mar 15, 2019 10:08 pm
Ok, so I am compiling on version 2.3.
If it does give you compile errors, can you paste the errors here?
Roberto.
User avatar
Posts: 86
Joined: Fri Sep 01, 2017 8:15 am
Location: Severna Park, MD
PostPosted: Sat Mar 16, 2019 10:12 am
I get an error with 2.3 but it's different from the others.

Sorry, I'm a beginner with this language and haven't been able to figure out how to fix this missing WiFiManager.h file error.

I used the verbose option when I compiled.
Code: Select all
Arduino: 1.8.5 (Windows 10), Board: "Adafruit HUZZAH ESP8266, 80 MHz, 115200, 4M (3M SPIFFS)"

C:\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Arduino\hardware -hardware C:\Users\Loose\AppData\Local\Arduino15\packages -tools C:\Arduino\tools-builder -tools C:\Arduino\hardware\tools\avr -tools C:\Users\Loose\AppData\Local\Arduino15\packages -built-in-libraries C:\Arduino\libraries -libraries C:\Users\Loose\Documents\Arduino\libraries -fqbn=esp8266:esp8266:huzzah:CpuFrequency=80,UploadSpeed=115200,FlashSize=4M3M -ide-version=10805 -build-path C:\Users\Loose\AppData\Local\Temp\arduino_build_558683 -warnings=all -build-cache C:\Users\Loose\AppData\Local\Temp\arduino_cache_59280 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.xtensa-lx106-elf-gcc.path=C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2 -prefs=runtime.tools.mkspiffs.path=C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\mkspiffs\0.1.2 -prefs=runtime.tools.esptool.path=C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\esptool\0.4.9 -verbose C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino
C:\Arduino\arduino-builder -compile -logger=machine -hardware C:\Arduino\hardware -hardware C:\Users\Loose\AppData\Local\Arduino15\packages -tools C:\Arduino\tools-builder -tools C:\Arduino\hardware\tools\avr -tools C:\Users\Loose\AppData\Local\Arduino15\packages -built-in-libraries C:\Arduino\libraries -libraries C:\Users\Loose\Documents\Arduino\libraries -fqbn=esp8266:esp8266:huzzah:CpuFrequency=80,UploadSpeed=115200,FlashSize=4M3M -ide-version=10805 -build-path C:\Users\Loose\AppData\Local\Temp\arduino_build_558683 -warnings=all -build-cache C:\Users\Loose\AppData\Local\Temp\arduino_cache_59280 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.xtensa-lx106-elf-gcc.path=C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2 -prefs=runtime.tools.mkspiffs.path=C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\mkspiffs\0.1.2 -prefs=runtime.tools.esptool.path=C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\esptool\0.4.9 -verbose C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino
Using board 'huzzah' from platform in folder: C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0
Using core 'esp8266' from platform in folder: C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0
Detecting libraries used...

"C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/include" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/lwip/include" "-IC:\Users\Loose\AppData\Local\Temp\arduino_build_558683/core" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11  -ffunction-sections -fdata-sections -w -x c++ -E -CC -DF_CPU=80000000L -DLWIP_OPEN_SRC   -DARDUINO=10805 -DARDUINO_ESP8266_ESP12 -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_ESP12"  -DESP8266 "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\adafruit" "C:\Users\Loose\AppData\Local\Temp\arduino_build_558683\sketch\Cloud_Wifi_Hub_Sal.ino.cpp" -o "nul"

"C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/include" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/lwip/include" "-IC:\Users\Loose\AppData\Local\Temp\arduino_build_558683/core" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11  -ffunction-sections -fdata-sections -w -x c++ -E -CC -DF_CPU=80000000L -DLWIP_OPEN_SRC   -DARDUINO=10805 -DARDUINO_ESP8266_ESP12 -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_ESP12"  -DESP8266 "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\adafruit" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src" "C:\Users\Loose\AppData\Local\Temp\arduino_build_558683\sketch\Cloud_Wifi_Hub_Sal.ino.cpp" -o "nul"

"C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/include" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/lwip/include" "-IC:\Users\Loose\AppData\Local\Temp\arduino_build_558683/core" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11  -ffunction-sections -fdata-sections -w -x c++ -E -CC -DF_CPU=80000000L -DLWIP_OPEN_SRC   -DARDUINO=10805 -DARDUINO_ESP8266_ESP12 -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_ESP12"  -DESP8266 "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\adafruit" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src" "-IC:\Users\Loose\Documents\Arduino\libraries\PubSubClient" "C:\Users\Loose\AppData\Local\Temp\arduino_build_558683\sketch\Cloud_Wifi_Hub_Sal.ino.cpp" -o "nul"

"C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/include" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/lwip/include" "-IC:\Users\Loose\AppData\Local\Temp\arduino_build_558683/core" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11  -ffunction-sections -fdata-sections -w -x c++ -E -CC -DF_CPU=80000000L -DLWIP_OPEN_SRC   -DARDUINO=10805 -DARDUINO_ESP8266_ESP12 -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_ESP12"  -DESP8266 "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\adafruit" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src" "-IC:\Users\Loose\Documents\Arduino\libraries\PubSubClient" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src" "C:\Users\Loose\AppData\Local\Temp\arduino_build_558683\sketch\Cloud_Wifi_Hub_Sal.ino.cpp" -o "nul"

"C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/include" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/lwip/include" "-IC:\Users\Loose\AppData\Local\Temp\arduino_build_558683/core" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11  -ffunction-sections -fdata-sections -w -x c++ -E -CC -DF_CPU=80000000L -DLWIP_OPEN_SRC   -DARDUINO=10805 -DARDUINO_ESP8266_ESP12 -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_ESP12"  -DESP8266 "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\adafruit" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src" "-IC:\Users\Loose\Documents\Arduino\libraries\PubSubClient" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src" "C:\Users\Loose\AppData\Local\Temp\arduino_build_558683\sketch\Cloud_Wifi_Hub_Sal.ino.cpp" -o "nul"

"C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/include" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/lwip/include" "-IC:\Users\Loose\AppData\Local\Temp\arduino_build_558683/core" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11  -ffunction-sections -fdata-sections -w -x c++ -E -CC -DF_CPU=80000000L -DLWIP_OPEN_SRC   -DARDUINO=10805 -DARDUINO_ESP8266_ESP12 -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_ESP12"  -DESP8266 "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\adafruit" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src" "-IC:\Users\Loose\Documents\Arduino\libraries\PubSubClient" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266httpUpdate\src" "C:\Users\Loose\AppData\Local\Temp\arduino_build_558683\sketch\Cloud_Wifi_Hub_Sal.ino.cpp" -o "nul"

"C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/include" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/lwip/include" "-IC:\Users\Loose\AppData\Local\Temp\arduino_build_558683/core" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11  -ffunction-sections -fdata-sections -w -x c++ -E -CC -DF_CPU=80000000L -DLWIP_OPEN_SRC   -DARDUINO=10805 -DARDUINO_ESP8266_ESP12 -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_ESP12"  -DESP8266 "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\adafruit" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src" "-IC:\Users\Loose\Documents\Arduino\libraries\PubSubClient" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266httpUpdate\src" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266HTTPClient\src" "C:\Users\Loose\AppData\Local\Temp\arduino_build_558683\sketch\Cloud_Wifi_Hub_Sal.ino.cpp" -o "nul"

"C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/include" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0/tools/sdk/lwip/include" "-IC:\Users\Loose\AppData\Local\Temp\arduino_build_558683/core" -c -w -Os -g -mlongcalls -mtext-section-literals -fno-exceptions -fno-rtti -falign-functions=4 -std=c++11  -ffunction-sections -fdata-sections -w -x c++ -E -CC -DF_CPU=80000000L -DLWIP_OPEN_SRC   -DARDUINO=10805 -DARDUINO_ESP8266_ESP12 -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_ESP12"  -DESP8266 "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\adafruit" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src" "-IC:\Users\Loose\Documents\Arduino\libraries\PubSubClient" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266httpUpdate\src" "-IC:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266HTTPClient\src" "C:\Users\Loose\AppData\Local\Temp\arduino_build_558683\sketch\Cloud_Wifi_Hub_Sal.ino.cpp" -o "C:\Users\Loose\AppData\Local\Temp\arduino_build_558683\preproc\ctags_target_for_gcc_minus_e.cpp"

C:\Users\Loose\Documents\Arduino\Cloud_Wifi_Hub_Salinity\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal\Cloud_Wifi_Hub_Sal.ino:7:25: fatal error: WiFiManager.h: No such file or directory

 #include <WiFiManager.h>

                         ^

compilation terminated.

Using library ESP8266WiFi at version 1.0 in folder: C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi
Using library PubSubClient in folder: C:\Users\Loose\Documents\Arduino\libraries\PubSubClient (legacy)
Using library DNSServer at version 1.1.0 in folder: C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer
Using library ESP8266WebServer at version 1.0 in folder: C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer
Using library ESP8266httpUpdate at version 1.1 in folder: C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266httpUpdate
Using library ESP8266HTTPClient at version 1.1 in folder: C:\Users\Loose\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266HTTPClient
exit status 1
Error compiling for board Adafruit HUZZAH ESP8266.

Try to learn something about everything and everything about something... Thomas Huxley
210gal DT | 50gal sump/refug | Jebao DCP 10000 pump | RO 200-int skimmer | DIY built stand | DIY 160 led, 12 channel, 458 watt, on MakersLED 72" heatsink

Posts: 12459
Joined: Fri Mar 18, 2011 6:47 pm
PostPosted: Sat Mar 16, 2019 2:21 pm
Ahh.
You need the latest dev branch of the libraries.
Replace the contents of /Documents/Arduino/libraries with these ones: https://github.com/reefangel/Libraries/archive/dev.zip
Roberto.
Next

Return to Addons

Who is online

Users browsing this forum: No registered users and 2 guests