diff --git a/Cache.ino b/Cache.ino index fead6d7..4d0d75c 100644 --- a/Cache.ino +++ b/Cache.ino @@ -6,6 +6,12 @@ #include #include #include +#include "Stage.h" +#include "Colors.h" +#include "Tilt.h" +#include "LedNavigation.h" +#include "Rfid.h" +#include "Logbook.h" /** @@ -31,32 +37,13 @@ NeoPixelBus ring(LED_COUNT, LED_PIN); TinyGPSPlus gps; QMC5883LCompass compass; LSM6DS3 gyro; -MFRC522 mfrc522(RC522_CS_PIN, RC522_RST_PIN); // Create MFRC522 instance +MFRC522 mfrc522(RC522_CS_PIN, RC522_RST_PIN); -#define O_X_DOWN 0x01 -#define O_X_UP 0x02 -#define O_Y_DOWN 0x04 -#define O_Y_UP 0x08 -#define O_Z_DOWN 0x10 -#define O_Z_UP 0x20 -uint8_t currentOrientation; +uint8_t currentStage = 0; +std::vector stages{new Tilt(gyro, ring), new LedNavigation(compass, gps, ring), new Rfid(mfrc522), new Logbook()}; +Stage* stage = stages[0]; -#define colorSaturation 4 -RgbColor red(colorSaturation, 0, 0); -RgbColor green(0, colorSaturation, 0); -RgbColor blue(0, 0, colorSaturation); -RgbColor white(colorSaturation); -RgbColor black(0); - -bool blinker = false; - -uint8_t stage = 0; - -uint8_t tiltSequence[] = {O_Z_DOWN, O_Y_DOWN, O_Z_DOWN, O_X_UP, O_Y_DOWN, O_Z_DOWN, 0x00}; -uint8_t tiltPointer = 0; - -const double TARGET_LAT = 48.4168602, TARGET_LON = 9.9433157; void setup() { @@ -69,25 +56,6 @@ void setup() ring.Begin(); ring.Show(); - //Over-ride default settings if desired - gyro.settings.gyroEnabled = 1; //Can be 0 or 1 - gyro.settings.gyroRange = 2000; //Max deg/s. Can be: 125, 245, 500, 1000, 2000 - gyro.settings.gyroSampleRate = 104; //Hz. Can be: 13, 26, 52, 104, 208, 416, 833, 1666 - gyro.settings.gyroBandWidth = 200; //Hz. Can be: 50, 100, 200, 400; - - gyro.settings.accelEnabled = 1; - gyro.settings.accelRange = 16; //Max G force readable. Can be: 2, 4, 8, 16 - gyro.settings.accelSampleRate = 833; //Hz. Can be: 13, 26, 52, 104, 208, 416, 833, 1666, 3332, 6664, 13330 - gyro.settings.accelBandWidth = 200; //Hz. Can be: 50, 100, 200, 400; - - // Set orientation threshold - gyro.writeRegister(LSM6DS3_ACC_GYRO_TAP_THS_6D, LSM6DS3_ACC_GYRO_SIXD_THS_60_degree); - // Enable low pass filter 2 - gyro.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0x10); - gyro.writeRegister(LSM6DS3_ACC_GYRO_CTRL8_XL, 0x01); - // Enable interrupt - gyro.writeRegister(LSM6DS3_ACC_GYRO_MD1_CFG, LSM6DS3_ACC_GYRO_INT1_6D_ENABLED); - gyro.begin(); compass.init(); @@ -112,189 +80,10 @@ void setup() void loop() { - switch(stage) { - case 0: - stageTilt(); - break; - case 1: - stageGotoPlayground(); - break; - default: - Serial.println("Not implemented!"); - } - - smartDelay(1000); - - if (millis() > 5000 && gps.charsProcessed() < 10) - Serial.println(F("No GPS data received: check wiring")); -} - -void smartDelay(unsigned long ms) -{ - unsigned long start = millis(); - do - { - while (Serial2.available()) - gps.encode(Serial2.read()); - stageRfid(); - } while (millis() - start < ms); + stage->handle(); } -void printDateTime(TinyGPSDate &d, TinyGPSTime &t) -{ - if (d.isValid()) - { - char sz[32]; - sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year()); - Serial.print(sz); - } - - if (t.isValid()) - { - char sz[32]; - sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second()); - Serial.print(sz); - } +void nextStage() { + stage = stages[currentStage++]; + stage->init(); } - -void stageTilt() { - uint8_t orientation; - gyro.readRegister(&orientation, LSM6DS3_ACC_GYRO_D6D_SRC); - - if(currentOrientation == orientation) { - return; - } - - currentOrientation = orientation; - - if(orientation == tiltSequence[tiltPointer]) { - tiltPointer++; - if(tiltSequence[tiltPointer] == 0) { - for(uint8_t i = 0; i < 10; i++) { - ring.ClearTo(white); - ring.Show(); - smartDelay(200); - ring.ClearTo(green); - ring.Show(); - smartDelay(200); - } - return; - } - ring.ClearTo(black); - ring.Show(); - smartDelay(500); - ring.ClearTo(green); - ring.Show(); - return; - } - - tiltPointer = 0; - ring.ClearTo(red); - ring.Show(); - - /*switch(orientation){ - case O_X_DOWN: - Serial.println("X down"); - break; - case O_X_UP: - Serial.println("X up"); - break; - case O_Y_DOWN: - Serial.println("Y down"); - break; - case O_Y_UP: - Serial.println("Y up"); - break; - case O_Z_DOWN: - Serial.println("Z down"); - break; - case O_Z_UP: - Serial.println("Z up"); - break; - default: - Serial.println("Unknown orientation"); - } - - - char orientationString[9]; - itoa(orientation, orientationString, 2); - Serial.print("\nOrientation:\n"); - Serial.printf("%s", orientationString);*/ -} - -void stageGotoPlayground() { - compass.read(); - - printDateTime(gps.date, gps.time); - - if(gps.satellites.isValid()) - { - Serial.printf("%d ", gps.satellites.value()); - } - - ring.ClearTo(black); - - if(gps.location.isValid()) { - Serial.printf("%f, %f, a: %d", gps.location.lat(), gps.location.lng(), gps.location.age()); - Serial.println(); - - unsigned long distanceMeters = - (unsigned long)TinyGPSPlus::distanceBetween( - gps.location.lat(), - gps.location.lng(), - TARGET_LAT, - TARGET_LON); - - int16_t course = - TinyGPSPlus::courseTo( - gps.location.lat(), - gps.location.lng(), - TARGET_LAT, - TARGET_LON); - - - int16_t azimuth = compass.getAzimuth(); - - char myArray[3]; - compass.getDirection(myArray, azimuth); - - Serial.print(" Azimuth: "); - Serial.print(azimuth); - Serial.print(" Direction: "); - Serial.print(myArray[0]); - Serial.print(myArray[1]); - Serial.print(myArray[2]); - - // Offset between LED #0 and azimuth == 0 - int16_t ledOffset = 90; - - Serial.printf(" d: %lu c: %d ang: %d", distanceMeters, course, (uint16_t)round(azimuth + ledOffset + course + 11.25f)); - - uint16_t ledIndex = (uint16_t)round((azimuth + ledOffset + course + 11.25f)/22.5) % 16; - ring.SetPixelColor(ledIndex, green); - } else { - if(blinker) { - ring.ClearTo(red); - } - blinker = !blinker; - } - Serial.println(); - Serial.println(); - - ring.Show(); -} - -void stageRfid() { - // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. - if ( ! mfrc522.PICC_IsNewCardPresent()) { - return; - } - - // Select one of the cards - if ( ! mfrc522.PICC_ReadCardSerial()) { - return; - } - - // Dump debug info about the card; PICC_HaltA() is automatically called - mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); -} \ No newline at end of file diff --git a/Colors.h b/Colors.h new file mode 100644 index 0000000..35a4901 --- /dev/null +++ b/Colors.h @@ -0,0 +1,13 @@ +#ifndef Colors_h +#define Colors_h + +#include + +#define colorSaturation 4 +const RgbColor red(colorSaturation, 0, 0); +const RgbColor green(0, colorSaturation, 0); +const RgbColor blue(0, 0, colorSaturation); +const RgbColor white(colorSaturation); +const RgbColor black(0); + +#endif \ No newline at end of file diff --git a/LedNavigation.cpp b/LedNavigation.cpp new file mode 100644 index 0000000..5b43b59 --- /dev/null +++ b/LedNavigation.cpp @@ -0,0 +1,96 @@ +#include "LedNavigation.h" + +void LedNavigation::handle() { + _compass.read(); + + _printDateTime(_gps.date, _gps.time); + + if(_gps.satellites.isValid()) + { + Serial.printf("%d ", _gps.satellites.value()); + } + + _ring.ClearTo(black); + + if(_gps.location.isValid()) { + Serial.printf("%f, %f, a: %d", _gps.location.lat(), _gps.location.lng(), _gps.location.age()); + Serial.println(); + + unsigned long distanceMeters = + (unsigned long)TinyGPSPlus::distanceBetween( + _gps.location.lat(), + _gps.location.lng(), + TARGET_LAT, + TARGET_LON); + + int16_t course = + TinyGPSPlus::courseTo( + _gps.location.lat(), + _gps.location.lng(), + TARGET_LAT, + TARGET_LON); + + + int16_t azimuth = _compass.getAzimuth(); + + char myArray[3]; + _compass.getDirection(myArray, azimuth); + + Serial.print(" Azimuth: "); + Serial.print(azimuth); + Serial.print(" Direction: "); + Serial.print(myArray[0]); + Serial.print(myArray[1]); + Serial.print(myArray[2]); + + // Offset between LED #0 and azimuth == 0 + int16_t ledOffset = 90; + + Serial.printf(" d: %lu c: %d ang: %d", distanceMeters, course, (uint16_t)round(azimuth + ledOffset + course + 11.25f)); + + uint16_t ledIndex = (uint16_t)round((azimuth + ledOffset + course + 11.25f)/22.5) % 16; + _ring.SetPixelColor(ledIndex, green); + } else { + if(_blinker) { + _ring.ClearTo(red); + } + _blinker = !_blinker; + } + Serial.println(); + Serial.println(); + + _ring.Show(); + + _smartDelay(500); + + if (millis() > 5000 && _gps.charsProcessed() < 10) { + Serial.println(F("No GPS data received: check wiring")); + } +}; + + +void LedNavigation::_smartDelay(unsigned long ms) { + unsigned long start = millis(); + do + { + while (Serial2.available()) { + _gps.encode(Serial2.read()); + } + } while (millis() - start < ms); +}; + +void LedNavigation::_printDateTime(TinyGPSDate &d, TinyGPSTime &t) { + if (d.isValid()) + { + char sz[32]; + sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year()); + Serial.print(sz); + } + + if (t.isValid()) + { + char sz[32]; + sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second()); + Serial.print(sz); + } +}; diff --git a/LedNavigation.h b/LedNavigation.h new file mode 100644 index 0000000..e59d7a3 --- /dev/null +++ b/LedNavigation.h @@ -0,0 +1,27 @@ +#ifndef LedNavigation_h +#define LedNavigation_h + +#include +#include +#include +#include +#include "Stage.h" +#include "Colors.h" + +class LedNavigation: public Stage { + public: + LedNavigation(QMC5883LCompass &compass, TinyGPSPlus &gps, NeoPixelBus &ring): _compass(compass), _gps(gps), _ring(ring) + {}; + void handle(); + private: + const double TARGET_LAT = 48.4168602; + const double TARGET_LON = 9.9433157; + bool _blinker = false; + QMC5883LCompass _compass; + TinyGPSPlus _gps; + NeoPixelBus _ring; + void _smartDelay(unsigned long ms); + void _printDateTime(TinyGPSDate &d, TinyGPSTime &t); +}; + +#endif \ No newline at end of file diff --git a/Logbook.cpp b/Logbook.cpp new file mode 100644 index 0000000..6d814c1 --- /dev/null +++ b/Logbook.cpp @@ -0,0 +1,5 @@ +#include "Logbook.h" + +void Logbook::handle() { + // TODO start Hotspot and Webserver +}; \ No newline at end of file diff --git a/Logbook.h b/Logbook.h new file mode 100644 index 0000000..3a1d0b1 --- /dev/null +++ b/Logbook.h @@ -0,0 +1,11 @@ +#ifndef Logbook_h +#define Logbook_h + +#include "Stage.h" + +class Logbook: public Stage { + public: + void handle(); +}; + +#endif \ No newline at end of file diff --git a/Rfid.cpp b/Rfid.cpp new file mode 100644 index 0000000..23dd358 --- /dev/null +++ b/Rfid.cpp @@ -0,0 +1,16 @@ +#include "Rfid.h" + +void Rfid::handle() { + // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle. + if ( ! _mfrc522.PICC_IsNewCardPresent()) { + return; + } + + // Select one of the cards + if ( ! _mfrc522.PICC_ReadCardSerial()) { + return; + } + + // Dump debug info about the card; PICC_HaltA() is automatically called + _mfrc522.PICC_DumpToSerial(&(_mfrc522.uid)); +}; \ No newline at end of file diff --git a/Rfid.h b/Rfid.h new file mode 100644 index 0000000..5f04046 --- /dev/null +++ b/Rfid.h @@ -0,0 +1,16 @@ +#ifndef Rfid_h +#define Rfid_h + +#include "Stage.h" +#include + +class Rfid: public Stage { + public: + Rfid(MFRC522 &mfrc522): _mfrc522(mfrc522) + {}; + void handle(); + private: + MFRC522 _mfrc522; +}; + +#endif \ No newline at end of file diff --git a/Stage.h b/Stage.h new file mode 100644 index 0000000..992598a --- /dev/null +++ b/Stage.h @@ -0,0 +1,10 @@ +#ifndef Stage_h +#define Stage_h + +class Stage { + public: + virtual void init() {}; + virtual void handle(); +}; + +#endif \ No newline at end of file diff --git a/Tilt.cpp b/Tilt.cpp new file mode 100644 index 0000000..bb7d4f0 --- /dev/null +++ b/Tilt.cpp @@ -0,0 +1,91 @@ +#include + +void Tilt::init() { + + _gyro.writeRegister(LSM6DS3_ACC_GYRO_CTRL3_C, LSM6DS3_ACC_GYRO_SW_RESET_RESET_DEVICE); + + //Over-ride default settings if desired + _gyro.settings.gyroEnabled = 1; //Can be 0 or 1 + _gyro.settings.gyroRange = 2000; //Max deg/s. Can be: 125, 245, 500, 1000, 2000 + _gyro.settings.gyroSampleRate = 104; //Hz. Can be: 13, 26, 52, 104, 208, 416, 833, 1666 + _gyro.settings.gyroBandWidth = 200; //Hz. Can be: 50, 100, 200, 400; + + _gyro.settings.accelEnabled = 1; + _gyro.settings.accelRange = 16; //Max G force readable. Can be: 2, 4, 8, 16 + _gyro.settings.accelSampleRate = 833; //Hz. Can be: 13, 26, 52, 104, 208, 416, 833, 1666, 3332, 6664, 13330 + _gyro.settings.accelBandWidth = 200; //Hz. Can be: 50, 100, 200, 400; + + _gyro.begin(); + + // Set orientation threshold + _gyro.writeRegister(LSM6DS3_ACC_GYRO_TAP_THS_6D, LSM6DS3_ACC_GYRO_SIXD_THS_60_degree); + // Enable low pass filter 2 + _gyro.writeRegister(LSM6DS3_ACC_GYRO_TAP_CFG1, 0x10); + _gyro.writeRegister(LSM6DS3_ACC_GYRO_CTRL8_XL, 0x01); + // Enable interrupt + _gyro.writeRegister(LSM6DS3_ACC_GYRO_MD1_CFG, LSM6DS3_ACC_GYRO_INT1_6D_ENABLED); +}; + +void Tilt::handle() { + uint8_t orientation; + _gyro.readRegister(&orientation, LSM6DS3_ACC_GYRO_D6D_SRC); + + if(_currentOrientation == orientation) { + return; + } + + _currentOrientation = orientation; + + if(orientation == _tiltSequence[_tiltPointer++]) { + if(_tiltSequence.size() == _tiltPointer) { + for(uint8_t i = 0; i < 10; i++) { + _ring.ClearTo(white); + _ring.Show(); + sleep(200); + _ring.ClearTo(green); + _ring.Show(); + sleep(200); + } + return; + } + _ring.ClearTo(black); + _ring.Show(); + sleep(500); + _ring.ClearTo(green); + _ring.Show(); + return; + } + + _tiltPointer = 0; + _ring.ClearTo(red); + _ring.Show(); + + /*switch(orientation){ + case O_X_DOWN: + Serial.println("X down"); + break; + case O_X_UP: + Serial.println("X up"); + break; + case O_Y_DOWN: + Serial.println("Y down"); + break; + case O_Y_UP: + Serial.println("Y up"); + break; + case O_Z_DOWN: + Serial.println("Z down"); + break; + case O_Z_UP: + Serial.println("Z up"); + break; + default: + Serial.println("Unknown orientation"); + } + + + char orientationString[9]; + itoa(orientation, orientationString, 2); + Serial.print("\nOrientation:\n"); + Serial.printf("%s", orientationString);*/ +}; \ No newline at end of file diff --git a/Tilt.h b/Tilt.h new file mode 100644 index 0000000..334129f --- /dev/null +++ b/Tilt.h @@ -0,0 +1,30 @@ +#ifndef Tilt_h +#define Tilt_h + +#include +#include +#include "Stage.h" +#include "Colors.h" + +#define O_X_DOWN 0x01 +#define O_X_UP 0x02 +#define O_Y_DOWN 0x04 +#define O_Y_UP 0x08 +#define O_Z_DOWN 0x10 +#define O_Z_UP 0x20 + +class Tilt: public Stage { + public: + Tilt(LSM6DS3 &gyro, NeoPixelBus &ring): _gyro(gyro), _ring(ring) { + }; + void init(); + void handle(); + private: + std::vector _tiltSequence{O_Z_DOWN, O_Y_DOWN, O_Z_DOWN, O_X_UP, O_Y_DOWN, O_Z_DOWN}; + uint8_t _tiltPointer = 0; + uint8_t _currentOrientation; + LSM6DS3 _gyro; + NeoPixelBus _ring; +}; + +#endif \ No newline at end of file