Hi everyone…
I have a bit of experience with arduino, and have had luck getting through the API, but I’m stumped with uploading new firmware. It is a particular program that is giving me troubles… only two stock libraries.
I am thinking it may be a memory issue, but this is smaller than the arduino code I developed and that was under 30kB FLASH and about 1.5kBSRAM. It happens DEBUG_ON or not…
Code:
#include "Adafruit_DHT/Adafruit_DHT.h"
#include "LiquidCrystal/LiquidCrystal.h"
// -----------------------------------
// WiFi Controller
// -----------------------------------
#define DEBUG_ON
#define DISPLAY_UPDATE_TIME 3000UL
#define DIMMER_PIN D1
#define NUMBER_OF_MESSAGE_TYPES 17
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21
#define DHT_SENSOR_PIN D6
#define NUMBER_OF_ACTION_BUTTONS 5
//
#ifdef DEBUG_ON
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTLN(x) Serial.println(x)
#define SERIAL_START(x) Serial.begin(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define SERIAL_START(x)
#endif
//
typedef enum{
LCD_WIND, LCD_TIME, LCD_ALARM_STATUS, LCD_GARAGE, LCD_GUEST_GARAGE, LCD_IP_ADDRESS, LCD_TEMPERATURE, LCD_AC_SETPOINT, LCD_OUTSIDE_TEMP, LCD_WEATHER, LCD_FORECAST, LCD_MESSAGE, LCD_HI_LOW, LCD_EMAIL}
lcdState;
//
lcdState state = LCD_TIME; // display start on Time
//
LiquidCrystal lcd(D0, D1, D2, D3, D4, D5);
//
DHT dht(DHT_SENSOR_PIN, DHTTYPE);
//
//
boolean messageFlag = false;
unsigned long myTimerStart;
unsigned long myTimerDuration;
int mySignal = 0;
boolean lightOn;
boolean relayState;
boolean garageOpen = false;
boolean guestGarageOpen = false;
char customMessage [30];
char weatherCondition[30] = {
" Not Yet Reported"};
char weatherForecast[30] = {
" Not Yet Reported"};
int outdoorTemp = -99;
int outdoorHumid = -99;
int todayHigh = -99;
int todayLow = -99;
int airconSetpoint = 78;
int alarmArmed = -1;
int windSpeed = 99;
char windDirection[6] = {
"ZZZ"};
char myCharBuffer[30];
byte brightLevel = 0;
byte oldBrightLevel;
int emailCount = -1;
const char *messageType[NUMBER_OF_MESSAGE_TYPES] = {
"?ledStatus=", "?alarmState=", "?garageState=", "?guestGarageState=", "?weatherCondition=", "?outsideTemp=", "?outsideHumid=", "?airconSetpoint=", "?weatherForecast=", "?messageData=", "?todayHigh=", "?todayLow=", "?windSpeed=", "?windDirection=", "?relayState=", "?brightLevel=", "?emailCount="};
//
const char *dayOfWeek[] = {
" Sunday"," Monday", " Tuesday", " Wednesday", " Thursday", " Friday", " Saturday"};
//
byte buttonPin[NUMBER_OF_ACTION_BUTTONS] = {
A0, A1, A2, A3, A4};
byte lastButtonState[NUMBER_OF_ACTION_BUTTONS];
//
// name the pins
int led1 = D0;
int led2 = D1;
int led3 = D7;
unsigned long startMillis;
int blinkOn = 0;
// This routine runs only once upon reset
void setup()
{
SERIAL_START(9600);
//Register our Spark function here
Spark.function("led", ledControl);
Spark.function("blinkLed", blinkLed);
Spark.function("getMyData", getMyData);
// Configure the pins to be outputs
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
dht.begin();
// Initialize both the LEDs to be OFF
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
}
// This routine loops forever
void loop()
{
if(blinkOn)
{
if (millis() - startMillis > 100UL)
{
digitalWrite(led3,!digitalRead(led3));
startMillis = millis();
}
}
else
{
digitalWrite(led3,LOW);
}
lcdUpdate();
getTime();
messageTimer();
for (byte i = 0; i < NUMBER_OF_ACTION_BUTTONS; i++)
{
byte buttonState = digitalRead(buttonPin[i]);
if (buttonState == LOW && lastButtonState[i] == HIGH)
{
buttonPress(i);
}
lastButtonState[i] = buttonState;
}
}
//
void buttonPress(int buttonNumber)
{
delay(1);
}
//
void getTime()
{
static unsigned long lastTimeSync;
if (millis() - lastTimeSync > 3600UL)
{
Spark.syncTime();
lastTimeSync = millis();
}
}
//
void lcdUpdate()
{
static unsigned long lastDisplayChangeTime;
if (millis() - lastDisplayChangeTime >= DISPLAY_UPDATE_TIME)
{
switch (state)
{
case LCD_TIME:
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
DEBUG_PRINT(F("Time: "));
DEBUG_PRINT(Time.hourFormat12());
DEBUG_PRINT(F(":"));
DEBUG_PRINT(Time.minute());
DEBUG_PRINTLN(Time.isAM() ? "a" : "p");
DEBUG_PRINTLN(dayOfWeek[Time.weekday() - 1]);
//lcd.print(dayOfWeek[weekday() - 1]);
displayStatus();
if (emailCount != -1)
state = LCD_EMAIL;
else
state = LCD_ALARM_STATUS;
break;
//
case LCD_EMAIL:
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" Email Count"));
DEBUG_PRINT(F("emails: "));
lcd.setCursor(0,2);
lcd.print(F(" "));
lcd.print(emailCount);
DEBUG_PRINTLN(emailCount);
displayStatus();
state = LCD_ALARM_STATUS;
break;
//
case LCD_ALARM_STATUS:
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" Alarm Status"));
DEBUG_PRINT(F("Alm: "));
lcd.setCursor(0,2);
if (alarmArmed == 0)
{
lcd.print(F(" Not Armed"));
}
else if (alarmArmed == 1)
{
lcd.print(F(" Armed"));
}
else
{
lcd.print(F(" Not Yet Reported"));
}
DEBUG_PRINTLN(alarmArmed ? F("Yes") : F("NO"));
displayStatus();
state = LCD_GARAGE;
break;
//
case LCD_GARAGE:
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" Main Garage"));
DEBUG_PRINT(F("Garage: "));
lcd.setCursor(0,2);
if (garageOpen == 0)
{
lcd.print(F(" Closed"));
}
else if (garageOpen == 1)
{
lcd.print(F(" Open"));
}
else
{
lcd.print(F(" Not Yet Reported"));
}
DEBUG_PRINTLN(garageOpen ? F("OPEN") : F("CLOSE"));
displayStatus();
state = LCD_GUEST_GARAGE;
break;
//
case LCD_GUEST_GARAGE:
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" Guest Garage"));
DEBUG_PRINT(F("Guest: "));
lcd.setCursor(0,2);
if (guestGarageOpen == 0)
{
lcd.print(F(" Closed"));
}
else if (guestGarageOpen == 1)
{
lcd.print(F(" Open"));
}
else
{
lcd.print(F(" Not Yet Reported"));
}
DEBUG_PRINTLN(guestGarageOpen ? F("OPEN") : F("CLOSE"));
displayStatus();
state = LCD_TEMPERATURE;
break;
//
case LCD_TEMPERATURE:
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" Temperture: "));
DEBUG_PRINT(F("Inside Temp:"));
lcd.print(dht.getTempFarenheit(), 0);
lcd.print(char(223));
lcd.print(F("F"));
lcd.setCursor(0,2);
lcd.print(F(" Humidity: "));
lcd.print(dht.getHumidity(), 0);
DEBUG_PRINT(F("Humidity:"));
DEBUG_PRINTLN(dht.getHumidity());
lcd.print(F("%"));
displayStatus();
state = LCD_AC_SETPOINT;
break;
case LCD_AC_SETPOINT:
//
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" A/C Setpoint"));
lcd.setCursor(0,2);
lcd.print(F(" "));
lcd.print(airconSetpoint);
lcd.print(char(223));
lcd.print(F("F"));
DEBUG_PRINT(F("A/C setpoint:"));
DEBUG_PRINTLN(airconSetpoint);
displayStatus();
state = LCD_OUTSIDE_TEMP;
break;
//
case LCD_OUTSIDE_TEMP:
//
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" Outdoor Temp:"));
DEBUG_PRINT(F("Ext. Temp:"));
lcd.print(outdoorTemp);
lcd.print(char(223));
lcd.print(F("F"));
DEBUG_PRINTLN(outdoorTemp);
lcd.setCursor(0,2);
lcd.print(F(" Humidity:"));
DEBUG_PRINT(F("Humidity:"));
lcd.print (outdoorHumid);
lcd.print(F("%"));
DEBUG_PRINTLN(outdoorHumid);
displayStatus();
state = LCD_WEATHER;
break;
//
case LCD_WEATHER:
//
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" Today's Weather"));
DEBUG_PRINT(F("Weather: "));
lcd.setCursor(0,2);
lcd.print(weatherCondition);
DEBUG_PRINTLN(weatherCondition);
displayStatus();
state = LCD_HI_LOW;
break;
//
case LCD_HI_LOW:
//
fastClearLCD();
DEBUG_PRINTLN(F("Weather Hi/Lows"));
timeDate();
lcd.setCursor(0,1);
lcd.print(F("Today's High: "));
lcd.print(todayHigh);
lcd.print(char(223));
lcd.print(F("F"));
lcd.setCursor(0,2);
lcd.print(F(" Low: "));
lcd.print (todayLow);
lcd.print(char(223));
lcd.print(F("F"));
displayStatus();
if (windSpeed > 2)
{
state = LCD_WIND;
}
else
{
state = LCD_FORECAST;
DEBUG_PRINTLN(F("wind too light to report..."));
}
break;
//
case LCD_WIND:
//
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" Winds Gusting"));
DEBUG_PRINT(F("Winds: "));
DEBUG_PRINTLN(windSpeed);
lcd.print(F(" "));
lcd.setCursor(1,2);
if (windSpeed < 10) lcd.print(F(" "));
lcd.print(windSpeed);
lcd.print(F("mph from the "));
lcd.print(windDirection);
displayStatus();
state = LCD_FORECAST;
break;
case LCD_FORECAST:
//
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" Tomorrow"));
DEBUG_PRINT(F("Forecast: "));
lcd.setCursor(0,2);
lcd.print(weatherForecast);
DEBUG_PRINTLN(weatherForecast);
displayStatus();
if (messageFlag)
state = LCD_MESSAGE;
else
state = LCD_IP_ADDRESS;
break;
//
case LCD_MESSAGE:
//
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
//
if (mySignal == 2 && brightLevel > 0)
{
for (int i = 0; i < 20; i++)
{
digitalWrite(DIMMER_PIN, HIGH);
delay(50);
digitalWrite(DIMMER_PIN,LOW);
delay(50);
}
analogWrite(DIMMER_PIN,brightLevel);
}
else if (mySignal == 1 && lightOn == 1)
{
beepTone();
}
if (mySignal != 0)
{
lastDisplayChangeTime - millis(); // give the message back the time lost in the flash/blinking
}
//
lcd.setCursor(0,1);
lcd.print(F(" *** Message ***"));
DEBUG_PRINT(F("Message: "));
lcd.setCursor(0,2);
lcd.print(customMessage);
DEBUG_PRINTLN(customMessage);
displayStatus();
state = LCD_IP_ADDRESS;
break;
//
case LCD_IP_ADDRESS:
//
fastClearLCD();
lcd.setCursor(0,0);
timeDate();
lcd.setCursor(0,1);
lcd.print(F(" IP Address"));
DEBUG_PRINT(F("IP Address: "));
lcd.setCursor(0,2);
lcd.print(" ");
for (byte thisByte = 0; thisByte < 4; thisByte++) // print the value of each byte of the IP address:
{
//lcd.print(Ethernet.localIP()[thisByte], DEC);
if (thisByte < 3) lcd.print(".");
#ifdef DEBUG_ON
//Serial.print(Ethernet.localIP()[thisByte], DEC);
#endif
if (thisByte < 3) DEBUG_PRINT(".");
else DEBUG_PRINTLN(F(" "));
}
lcd.print(F(" "));
displayStatus();
state = LCD_TIME;
break;
//
}
lastDisplayChangeTime = millis();
//DEBUG_PRINT(F("free ram:"));
//DEBUG_PRINTLN(freeRam());
}
}
//
// These Functions get called whenever there is a matching API request
//
int ledControl(String command)
{
int state = 0;
//find out the pin number and convert the ascii to integer
int pinNumber = (command.charAt(1) - '0') - 1;
//Sanity check to see if the pin numbers are within limits
if (pinNumber < 0 || pinNumber > 1) return -1;
// find out the state of the led
if(command.substring(3,7) == "HIGH") state = 1;
else if(command.substring(3,6) == "LOW") state = 0;
else return -1;
// write to the appropriate pin
digitalWrite(pinNumber, state);
return 1;
}
int blinkLed(String status)
{
if (status == "1")
{
blinkOn = 1;
//digitalWrite(led2,HIGH);
return 1;
}
else if (status == "0")
{
blinkOn = 0;
//digitalWrite(led2,LOW);
return 0;
}
else
{
return -1;
}
}
//
int getMyData(String myData)
{
delay(1);
return -1;
}
//
void fastClearLCD()
{
for (int i = 1; i < 3; i++)
{
lcd.setCursor(0,i);
for (int j = 0; j < 20; j++)
{
lcd.print(F(" "));
}
}
}
//
void timeDate()
{
if (Time.hourFormat12() < 10) lcd.print(F(" "));
lcd.print(Time.hourFormat12());
lcd.print(Time.minute() < 10 ? F(":0") : F(":"));
lcd.print(Time.minute());
lcd.print(Time.isAM() ? "am" : "pm");
lcd.setCursor(9,0);
if (Time.month() < 10) lcd.print(F(" "));
lcd.print(Time.month());
lcd.print(Time.day() < 10 ? F("/0") : F("/"));
lcd.print(Time.day());
lcd.print(F("/"));
lcd.print(Time.year());
}
//
void displayStatus()
{
lcd.setCursor(0,3);
lcd.print(emailCount < 0? 0 : emailCount);
if (emailCount == 1)
{
lcd.print(F(" eMail "));
}
else
{
lcd.print(F(" eMails "));
}
lcd.setCursor(11,3);
if (alarmArmed != 1)
{
lcd.print(F("Not Armed"));
}
else
{
lcd.print(F(" Armed"));
}
}
//
void beepTone()
{
}
void messageTimer()
{
if (millis() - myTimerStart >= myTimerDuration * 60000UL)
{
messageFlag = false;
mySignal = 0;
}
}