Nu har jag för första gången försökt mig på Arduino, men jag kom inte speciellt långt...
Använder Arduino IDE 1.6.4 på min trogna Windows XP maskin.
Följande kod kompilerar inte. Kompileringen avbryts med att ld.exe till synes crashar och avslutas av Windows. I IDE'n står det:
collect2.exe: error: ld returned 5 exit status
Error compiling
Att kompilera för Arduino Uno går inte, men ändrar jag till Arduino Mega går kompileringen igenom.
Det verkar ha nåt med kodstorleken att göra. Kommenterar jag t.ex. bort lcd.begin(16, 2); i setup() eller någon av casen i update_state_machine() så kompilerar den för Uno också. Vad är det jag missat....? Jag använder ju bara en liten del av tillgängligt RAM och ROM.
Koden i sin helhet är:
Kod: Markera allt
#include <LiquidCrystal.h>
#define BEEPER_PORT 13
#define STOP_COUNDNTDOWN_WIRE_PORT A1
#define DESTRUCT_WIRE_1_PORT A2
#define DESTRUCT_WIRE_2_PORT A3
#define DESTRUCT_WIRE_3_PORT A4
#define CASE_OPEN_SENSOR_PORT A5
enum States
{
ARM_CASE,
CASE_CLOSED_TIMEOUT,
CASE_CLOSED,
CASE_OPENED_DEBOUNCE,
CASE_OPENED_COUNTDOWN,
COUNTDOWN_STOPPED,
DESTRUCT_COUNTDOWN,
DESTRUCT_NOW,
};
enum States state;
unsigned long state_timeout_start;
unsigned long state_timeout_time;
// The 2x16 LCD shield
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// Check if case is open
bool isCaseOpen()
{
return digitalRead(CASE_OPEN_SENSOR_PORT) == HIGH;
}
// Check if stop countdown wire has been cut
bool isStopCoundownWireCut()
{
return digitalRead(STOP_COUNDNTDOWN_WIRE_PORT) == HIGH;
}
// Check if any of the destruct wires has been cut
bool isDestructWireCut()
{
return (digitalRead(DESTRUCT_WIRE_1_PORT) == HIGH) ||
(digitalRead(DESTRUCT_WIRE_2_PORT) == HIGH) ||
(digitalRead(DESTRUCT_WIRE_3_PORT) == HIGH);
}
unsigned long beep_time;
unsigned long beep_period_time_ms, beep_on_time_ms;
void setBeepRate(unsigned long period_time_ms, unsigned long on_time_ms)
{
beep_period_time_ms = period_time_ms;
beep_on_time_ms = on_time_ms;
}
void update_beep()
{
unsigned long elapsed = millis() - beep_time;
if (elapsed < beep_on_time_ms)
{
digitalWrite(BEEPER_PORT, HIGH);
}
else
{
digitalWrite(BEEPER_PORT, LOW);
}
if (elapsed > beep_period_time_ms)
{
beep_time += beep_period_time_ms;
}
}
void setup()
{
// Configure "cut wire" ports as digital inputs with pullup
pinMode(STOP_COUNDNTDOWN_WIRE_PORT, INPUT_PULLUP);
pinMode(DESTRUCT_WIRE_1_PORT, INPUT_PULLUP);
pinMode(DESTRUCT_WIRE_2_PORT, INPUT_PULLUP);
pinMode(DESTRUCT_WIRE_3_PORT, INPUT_PULLUP);
// Configure "case open" sensor port as digital input with pullup
pinMode(CASE_OPEN_SENSOR_PORT, INPUT_PULLUP);
pinMode(BEEPER_PORT, OUTPUT);
digitalWrite(BEEPER_PORT, LOW);
// Configure LCD, 16 columns, 2 rows
lcd.begin(16, 2);
beep_time = millis();
setBeepRate(1000, 0);
state = ARM_CASE;
Serial.begin(19200);
Serial.print("Start\n");
}
void loop()
{
update_state_machine();
}
void update_state_machine()
{
switch (state)
{
default:
case ARM_CASE:
if (!isCaseOpen())
{
state_timeout_start = millis();
state_timeout_time = 10*1000; // Wait in next state for 10 seconds
state = CASE_CLOSED_TIMEOUT;
setBeepRate(1000, 1000); // Constant beep
Serial.print("state = CASE_CLOSED_TIMEOUT\n");
}
break;
case CASE_CLOSED_TIMEOUT:
#if 1
if (isCaseOpen())
{
// Case was opened, go back to previous state
state = ARM_CASE;
setBeepRate(1000, 0); // Silent
Serial.print("state = ARM_CASE\n");
break;
}
if ((millis() - state_timeout_start) > state_timeout_time)
{
setBeepRate(5*1000, 100); // Short bip every 5 second
state = CASE_CLOSED;
Serial.print("state = CASE_CLOSED\n");
}
#endif
break;
case CASE_CLOSED:
#if 0
if (isCaseOpen())
{
state = CASE_OPENED_DEBOUNCE;
state_timeout_start = millis();
state_timeout_time = 2*1000; // Debounce state for 2 second
Serial.print("state = CASE_OPENED_DEBOUNCE\n");
}
#endif
break;
case CASE_OPENED_DEBOUNCE:
#if 0
if (!isCaseOpen())
{
// Case was closed, go back to previous state
state = CASE_CLOSED;
Serial.print("state = CASE_CLOSED\n");
break;
}
if ((millis() - state_timeout_start) > state_timeout_time)
{
state = CASE_OPENED_COUNTDOWN;
setBeepRate(1000, 100); // Short bip every second
Serial.print("state = CASE_OPENED_COUNTDOWN\n");
break;
}
#endif
break;
case CASE_OPENED_COUNTDOWN:
#if 1
if (isStopCoundownWireCut())
{
state = COUNTDOWN_STOPPED;
setBeepRate(1000, 0); // Silent
Serial.print("state = COUNTDOWN_STOPPED\n");
break;
}
if (isDestructWireCut())
{
state = DESTRUCT_COUNTDOWN;
setBeepRate(300, 100); // Fast short bips
Serial.print("state = DESTRUCT_COUNTDOWN\n");
break;
}
#endif
break;
case COUNTDOWN_STOPPED:
break;
case DESTRUCT_COUNTDOWN:
break;
case DESTRUCT_NOW:
break;
}
}