Error code:
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o): In function `__static_initialization_and_destruction_0':
Adafruit_RGBLCDShield/Adafruit_MCP23017.cpp:41: multiple definition of `Adafruit_MCP23017::begin(unsigned char)'
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o):Adafruit_MCP23017/Adafruit_MCP23017.cpp:110: first defined here
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o): In function `Adafruit_MCP23017::begin()':
Adafruit_RGBLCDShield/Adafruit_MCP23017.cpp:64: multiple definition of `Adafruit_MCP23017::begin()'
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o):Adafruit_MCP23017/Adafruit_MCP23017.cpp:128: first defined here
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o): In function `Adafruit_MCP23017::pinMode(unsigned char, unsigned char)':
Adafruit_RGBLCDShield/Adafruit_MCP23017.cpp:72: multiple definition of `Adafruit_MCP23017::pinMode(unsigned char, unsigned char)'
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o):Adafruit_MCP23017/Adafruit_MCP23017.cpp:134: first defined here
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o): In function `Adafruit_MCP23017::readGPIOAB()':
Adafruit_RGBLCDShield/Adafruit_MCP23017.cpp:104: multiple definition of `Adafruit_MCP23017::readGPIOAB()'
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o):Adafruit_MCP23017/Adafruit_MCP23017.cpp:141: first defined here
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o): In function `Adafruit_MCP23017::writeGPIOAB(unsigned short)':
Adafruit_RGBLCDShield/Adafruit_MCP23017.cpp:122: multiple definition of `Adafruit_MCP23017::writeGPIOAB(unsigned short)'
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o):Adafruit_MCP23017/Adafruit_MCP23017.cpp:181: first defined here
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o): In function `Adafruit_MCP23017::digitalWrite(unsigned char, unsigned char)':
Adafruit_RGBLCDShield/Adafruit_MCP23017.cpp:135: multiple definition of `Adafruit_MCP23017::digitalWrite(unsigned char, unsigned char)'
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o):Adafruit_MCP23017/Adafruit_MCP23017.cpp:60: first defined here
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o): In function `Adafruit_MCP23017::pullUp(unsigned char, unsigned char)':
Adafruit_RGBLCDShield/Adafruit_MCP23017.cpp:174: multiple definition of `Adafruit_MCP23017::pullUp(unsigned char, unsigned char)'
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o):Adafruit_MCP23017/Adafruit_MCP23017.cpp:206: first defined here
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o): In function `Adafruit_MCP23017::digitalRead(unsigned char)':
Adafruit_RGBLCDShield/Adafruit_MCP23017.cpp:211: multiple definition of `Adafruit_MCP23017::digitalRead(unsigned char)'
../../../build/target/user/platform-6/libuser.a(Adafruit_MCP23017.o):Adafruit_MCP23017/Adafruit_MCP23017.cpp:60: first defined here
collect2: error: ld returned 1 exit status
make: *** [dfa0388819b87ca9ebcf8141b7e161eaf0f8693f1673e73599cdcc6f67d6.elf] Error 1
Error: Could not compile. Please review your code.
Sketch Code:
/*********************
Fan Controller
by enginesong
Version 1 - August 14,2016
Ported to Particle - September 02, 2016
**********************/
// Included Libraries:
//#include "Adafruit_MCP23017/Adafruit_MCP23017.h"
#include "Adafruit_RGBLCDShield/Adafruit_RGBLCDShield.h"
#include "Adafruit_MAX31855/Adafruit_MAX31855.h"
#include "math.h"
// The shield uses the I2C SCL and SDA pins. On classic Arduinos
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
// However, you can connect other I2C sensors to the I2C bus and share
// the I2C bus.
Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
// These #defines make it easy to set the backlight color
#define OFF 0x0
#define RED 0x1
#define GREEN 0x2
#define YELLOW 0x3
#define BLUE 0x4
#define VIOLET 0x5
#define TEAL 0x6
#define WHITE 0x7
// Create a thermocouple instance with software SPI on any three digital IO pins.
#define MAXDO 3 //connect DO to Particle digital pin 3
#define MAXCS 4 //connect CS to Particle digital pin 4
#define MAXCLK 5 //connect CLK to Particle digital pin 5
// initialize the Thermocouple
Adafruit_MAX31855 thermocouple(MAXCLK, MAXCS, MAXDO);
////////////////////////////////////////////////////////////////////////////////////////
//int set_point[] = {90,250,500}; //set points for: Fan ON, Add wood, Over temp
int set_point[] = {75, 84, 90}; //test set points for: Fan ON, Add wood, Over temp
/*
--------------------------
EEPROM Addresses
--------------------------
0 - FAN on set point.
1 - Add wood/end of warm up set point.
2 - Over temp warning set point.
*/
////////////////////////////////////////////////////////////////////////////////////////
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int relayPin = 6; // the number of the relay pin
const int ledPin = 7; // the number of the LED pin
// Variables will change:
uint8_t ledState = LOW; // the current state of the LED output pin
uint8_t relayState = LOW; // the current state of the relay output pin
uint8_t buttonState; // the current reading from the button input pin
//int lastButtonState = LOW; // the previous reading from the input pin
uint8_t lastButtonState = LOW; // the previous reading from the input pin
//unsigned int reading = 0;
uint8_t auto_mode = LOW; // default is auto mode ON
uint8_t lastLedState = LOW; // the previous reading from the relay
uint8_t cooling_down = LOW; // initially will be warming up, not cooling down
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change :
const long interval = 10000; // time out interval (milliseconds). Used for pumps, etc.
// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
//need to be unsigned to prevent comparison errors with millis()
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long lastDebounceTime2 = 0; // the last time the output pin was toggled
//long debounceDelay = 50; // the debounce time; increase if the output flickers
unsigned long debounceDelay = 150; // the debounce time; increase if the output flickers, requires button hold down for minimum 150ms. Toggles Manual Mode.
unsigned long debounceDelay2 = 2000; // the debounce time; increase if the output flickers, requires LED change commanded for longer than this time. Toggles Relay.
unsigned long debounceDelay3 = 10000; // the debounce time; increase if the output flickers, requires relay change commanded for longer than this time. Determines warming up or cooling down.
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
lcd.clear();
lcd.setBacklight(BLUE);
// define pin types
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
pinMode(relayPin, OUTPUT);
// set initial LED and relay states
digitalWrite(ledPin, ledState);
digitalWrite(relayPin, relayState);
}
void loop() {
// read the state of the switch into a local variable:
uint8_t reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the button changed, due to noise or command, reset debouncing timer:
if (reading != lastButtonState) {
lastDebounceTime = millis(); //LED timer
}
//if the following is true, the button has been pressed ->toggle manual mode
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// toggle the LED if the new button state is HIGH, auto mode is ON and LED is OFF
if ((buttonState == HIGH) && (auto_mode == HIGH) && (ledState == LOW)) {
ledState = !ledState;
//relayState = !relayState;
auto_mode = !auto_mode; //toggle auto mode if button is pressed
lcd.clear();
debounceDelay2 = 1000; //shorter relay change delay due to manual button press
}
// toggle the LED if the new button state is HIGH, auto mode is OFF and LED is ON
else if ((buttonState == HIGH) && (auto_mode == LOW) && (ledState == HIGH)) {
ledState = !ledState;
auto_mode = !auto_mode; //toggle auto mode if button is pressed
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Auto Mode: ON");
delay(5000);
lcd.clear();
}
// Do not toggle the LED if the new button state is HIGH, auto mode is ON and LED is ON
else if ((buttonState == HIGH) && (auto_mode == HIGH) && (ledState == HIGH)) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Fan Already ON");
lcd.setCursor(0, 1);
lcd.print("Button Disabled!");
delay(5000);
lcd.clear();
}
// re-enable auto mode if the new button state is HIGH, auto mode is OFF and LED is OFF
else if ((buttonState == HIGH) && (auto_mode == LOW) && (ledState == LOW)) {
auto_mode = HIGH; //toggle auto mode if button is pressed
lcd.clear();
}
}
// set the LED:
if (!auto_mode) {
digitalWrite(ledPin, ledState); //relay follows
//digitalWrite(relayPin, relayState);
}
}
// Change display when in manual mode
if (!auto_mode) {
lcd.setBacklight(VIOLET); //manual mode active
lcd.setCursor(0, 0);
lcd.print(" Auto Mode: OFF");
lcd.setCursor(0, 1);
lcd.print(" Fan ON");
}
//normal automatic mode (if auto_mode is true)
if (auto_mode) {
debounceDelay2 = 10000; //longer relay debounce delay due to temperature change
//uint8_t buttons = lcd.readButtons();
double f = thermocouple.readFarenheit();
lcd.setCursor(0, 0);
if (isnan(f)) {
lcd.print("T/C Problem");
}
else {
if (f < 100.0) { //checks if 2 digits or 3 digits to report for display spacing
lcd.setCursor(4, 1); //set cursor to start of second row
lcd.print(" ");
lcd.setCursor(5, 1);
lcd.print(f, 0); //zero significant digits to the right of the decimal, no decimal either
}
else {
lcd.setCursor(4, 1);
lcd.print(f, 0);
}
lcd.setCursor(7, 1);
lcd.print(" degF");
}
//add millis timer(s) to make sure face color or switches don't change too often as temp passes through set points
if (f <= set_point[0]) {
ledState = LOW;
digitalWrite(ledPin, ledState); //turn ON LED, relay follows
lcd.setCursor(0, 0); //set cursor to start of top row
lcd.print("Fan Control OFF");
lcd.setBacklight(BLUE); //if temp is below normal range.
} //end if Relay is OFF arguements
else {
ledState = HIGH;
digitalWrite(ledPin, ledState); // turn ON LED, relay follows
if (f >= set_point[2]) {
//"Over Temp" warning Output here
lcd.setCursor(0, 0); //set cursor to start of top row
lcd.print(" !!!WARNING!!! ");
lcd.setBacklight(RED); //if temp is above normal range. High Temp trigger.
}
else if (f > set_point[1]) {
//No special notes for "Normal"
lcd.setCursor(0, 0); //set cursor to start of top row
lcd.print(" Normal Range ");
lcd.setBacklight(GREEN); //if temp is within normal range.
}
else {
lcd.setBacklight(WHITE); //if temp is within normal range but warming up or add wood.
lcd.setCursor(0, 0); //set cursor to start of top row
if (cooling_down == LOW) {
lcd.print(" Warming Up ");
}
else {
//"Add wood" Output here
lcd.print(" Add More Wood! ");
}
}
} //end if Relay is ON arguements
} //end if "auto_mode"
uint8_t buttons = lcd.readButtons();
if (buttons) {
int menu_cursor1 = 0;
lcd.setBacklight(WHITE);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Setpoint Menu ");
delay(2000);
lcd.setCursor(0,1);
lcd.print(" -Directions- ");
delay(2000);
lcd.setCursor(0,1);
lcd.print("LEFT: Back/Exits");
delay(2000);
lcd.setCursor(0,1);
lcd.print("UP/DOWN: scrolls");
delay(2000);
lcd.setCursor(0,1);
lcd.print("SELECT: selects ");
delay(2000);
while (1 > 0) {
buttons = lcd.readButtons();
if (buttons & BUTTON_LEFT) {
break; //only can exit while loop with a LEFT button press
}
//lcd.clear();
lcd.setCursor(0,0);
lcd.print("Select Setpoint ");
if (menu_cursor1 == 0) {
lcd.setCursor(0,1);
lcd.print(" -FAN turns on- ");
}
if (menu_cursor1 == 1) {
lcd.setCursor(0,1);
lcd.print(" -Add more wood-");
}
if (menu_cursor1 == 2) {
lcd.setCursor(0,1);
lcd.print("-Over temp warn-");
}
if (buttons & BUTTON_UP) {
menu_cursor1 = menu_cursor1 - 1;
if (menu_cursor1 >= 2) {
menu_cursor1 = 2;
}
}
if (buttons & BUTTON_DOWN) {
menu_cursor1 = menu_cursor1 + 1;
if (menu_cursor1 <= 0) {
menu_cursor1 = 0;
}
}
if ((buttons & BUTTON_SELECT) || (buttons & BUTTON_RIGHT)) { //either selection
lcd.clear();
int setpoint0 = EEPROM.read(0);
int setpoint0_new = setpoint0;
int setpoint1 = EEPROM.read(1);
int setpoint1_new = setpoint1;
int setpoint2 = EEPROM.read(2);
int setpoint2_new = setpoint2;
while (1 > 0) {
buttons = lcd.readButtons();
if (buttons & BUTTON_LEFT) {
break; //only can exit while loop with a LEFT button press
}
if (menu_cursor1 == 0) {
//lcd.clear();
lcd.setCursor(0,0);
lcd.print("Fan ON at:");
lcd.setCursor(11,0);
lcd.print(setpoint0);
lcd.setCursor(15,0);
lcd.print("F");
lcd.setCursor(0,1);
lcd.print("New Setpoint ");
lcd.setCursor(13,1);
lcd.print(setpoint0_new);
if (buttons & BUTTON_UP) {
setpoint0_new = setpoint0_new + 5;
}
if (buttons & BUTTON_DOWN) {
setpoint0_new = setpoint0_new - 5;
}
if ((buttons & BUTTON_SELECT) || (buttons & BUTTON_RIGHT)) { //either selection
//EEPROM.write(0, setpoint0_new); //save change to EEPROM
EEPROM.put(0, setpoint0_new); //save change to EEPROM
setpoint0 = setpoint0_new;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Setpoint Updated");
lcd.setCursor(0,1);
lcd.print("Fan ON at:");
lcd.setCursor(11,1);
lcd.print(setpoint0);
lcd.setCursor(15,1);
lcd.print("F");
delay(2500);
break; //exit while loop after making selection, return to previous menu
} //end of making new setpoint
} // fan ON setpoint
if (menu_cursor1 == 1) {
//lcd.clear();
lcd.setCursor(0,0);
lcd.print("Add Wood:");
lcd.setCursor(13,0);
lcd.print(setpoint1);
lcd.setCursor(15,0);
lcd.print("F");
lcd.setCursor(0,1);
lcd.print("New Setpoint ");
lcd.setCursor(13,1);
lcd.print(setpoint1_new);
if (buttons & BUTTON_UP) {
setpoint1_new = setpoint1_new + 5;
}
if (buttons & BUTTON_DOWN) {
setpoint1_new = setpoint1_new - 5;
}
if ((buttons & BUTTON_SELECT) || (buttons & BUTTON_RIGHT)) { //either selection
//EEPROM.write(1, setpoint1_new); //save change to EEPROM
EEPROM.put(1, setpoint1_new); //save change to EEPROM
setpoint1 = setpoint1_new;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Setpoint Updated");
lcd.setCursor(0,1);
lcd.print("Add Wood:");
lcd.setCursor(12,1);
lcd.print(setpoint1);
lcd.setCursor(15,1);
lcd.print("F");
delay(2500);
break; //exit while loop after making selection, return to previous menu
} //end of making new setpoint
} // add wood setpoint
if (menu_cursor1 == 2) {
//lcd.clear();
lcd.setCursor(0,0);
lcd.print("Warning at:");
lcd.setCursor(12,0);
lcd.print(setpoint2);
lcd.setCursor(15,0);
lcd.print("F");
lcd.setCursor(0,1);
lcd.print("New Setpoint ");
lcd.setCursor(13,1);
lcd.print(setpoint2_new);
if (buttons & BUTTON_UP) {
setpoint2_new = setpoint2_new + 10;
}
if (buttons & BUTTON_DOWN) {
setpoint2_new = setpoint2_new - 10;
}
if ((buttons & BUTTON_SELECT) || (buttons & BUTTON_RIGHT)) { //either selection
//EEPROM.write(2, setpoint2_new); //save change to EEPROM
EEPROM.put(2, setpoint2_new); //save change to EEPROM
setpoint2 = setpoint2_new;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Setpoint Updated");
lcd.setCursor(0,1);
lcd.print("Warning at:");
lcd.setCursor(12,1);
lcd.print(setpoint2);
lcd.setCursor(15,1);
lcd.print("F");
delay(2500);
break; //exit while loop after making selection, return to previous menu
} //end of making new setpoint
} // warning setpoint
} //while still in setpoint value menu
} //end of setpoint value
} //end setpoint select menu
lcd.clear();
} //end buttons/main menu
// If the LED changed, due to noise or command, reset debouncing timer:
if (ledState != lastLedState) {
lastDebounceTime2 = millis(); //Relay timer
}
//if the following is true, the LED has been commanded long enough ->toggle relay mode
if ((millis() - lastDebounceTime2) > debounceDelay2) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// Set relay state to LED state:
relayState = ledState;
digitalWrite(relayPin, relayState);
}
if ((millis() - lastDebounceTime2) > debounceDelay3) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
//relayState = ledState;
//digitalWrite(relayPin, relayState);
cooling_down = HIGH; // fan turned ON a long time ago, so must be cooling down
}
else {
cooling_down = LOW; //fan turned ON recently, so must be warming up
}
// save the reading. Next time through the loop, it will be the lastButtonState:
lastButtonState = reading;
lastLedState = ledState;
//delay(1000);
}