|
|
|
|
/*********
|
|
|
|
|
For display
|
|
|
|
|
GxEPD_Example : test example for e-Paper displays from Waveshare and from Dalian Good Display Inc.
|
|
|
|
|
//
|
|
|
|
|
// Created by Jean-Marc Zingg based on demo code from Good Display,
|
|
|
|
|
// available on http://www.e-paper-display.com/download_list/downloadcategoryid=34&isMode=false.html
|
|
|
|
|
//
|
|
|
|
|
// Supporting Arduino Forum Topics:
|
|
|
|
|
// Waveshare e-paper displays with SPI: http://forum.arduino.cc/index.php?topic=487007.0
|
|
|
|
|
// Good Dispay ePaper for Arduino : https://forum.arduino.cc/index.php?topic=436411.0
|
|
|
|
|
|
|
|
|
|
// mapping suggestion for ESP32, e.g. LOLIN32, see .../variants/.../pins_arduino.h for your board
|
|
|
|
|
// NOTE: there are variants with different pins for SPI ! CHECK SPI PINS OF YOUR BOARD
|
|
|
|
|
// BUSY -> 4, RST -> 16, DC -> 17, CS -> SS(5), CLK -> SCK(18), DIN -> MOSI(23), GND -> GND, 3.3V -> 3.3V
|
|
|
|
|
*********/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********
|
|
|
|
|
For communication
|
|
|
|
|
Rui Santos
|
|
|
|
|
Complete project details at https://RandomNerdTutorials.com/esp-now-one-to-many-esp32-esp8266/
|
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
of this software and associated documentation files.
|
|
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
*********/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// include library, include base class, make path known
|
|
|
|
|
#include <GxEPD.h> //->display
|
|
|
|
|
#include <esp_now.h>
|
|
|
|
|
#include <WiFi.h>
|
|
|
|
|
//#include "unease.h"
|
|
|
|
|
//#include "Tree_0.h"
|
|
|
|
|
//#include "Tree_of_unease_0.h"
|
|
|
|
|
//#include "Tree_1.h"
|
|
|
|
|
//#include "Tree_of_unease_1.h"
|
|
|
|
|
//#include "Tree_2.h"
|
|
|
|
|
//#include "Tree_of_unease_2.h"
|
|
|
|
|
//#include "Tree_3.h"
|
|
|
|
|
//#include "Tree_of_unease_3.h"
|
|
|
|
|
#include "Tree_4.h"
|
|
|
|
|
#include "Tree_of_unease_4.h"
|
|
|
|
|
|
|
|
|
|
PublishingHouse :: RandomForest :: TreeOfUnease treeOfUnease;
|
|
|
|
|
PublishingHouse :: RandomForest :: DecisionTree tree;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//const int randSeed = 6730/;
|
|
|
|
|
const int featureCount = 4;
|
|
|
|
|
const int treeNumber = 4;
|
|
|
|
|
int considerationStep = 0;
|
|
|
|
|
String considerationTraces = String();
|
|
|
|
|
const int verticalOffset = 19;
|
|
|
|
|
float lastObservation[featureCount] = { 0.0, 0.0, 0.0, 0.0 };
|
|
|
|
|
const char *answer;
|
|
|
|
|
const int answerPrefixLength = 3;
|
|
|
|
|
const char *answerPrefix[] = {
|
|
|
|
|
"It might be ",
|
|
|
|
|
"I think it is ",
|
|
|
|
|
"I would say it is "
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
///////////////////
|
|
|
|
|
///DISPLAY///
|
|
|
|
|
//////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// select the display class to use, only one
|
|
|
|
|
|
|
|
|
|
#include <GxGDEH0154D67/GxGDEH0154D67.h> // 1.54" b/w
|
|
|
|
|
|
|
|
|
|
// FreeFonts from Adafruit_GFX
|
|
|
|
|
//#include <Fonts/FreeMonoBold9pt7b.h>/
|
|
|
|
|
//#include <Fonts/FreeMonoBold12pt7b.h>//
|
|
|
|
|
#include <Fonts/FreeSans12pt7b.h>
|
|
|
|
|
#include <Fonts/FreeSansOblique12pt7b.h>
|
|
|
|
|
//#include <Fonts/FreeMonoBold18pt7b.h>/
|
|
|
|
|
//#include <Fonts/FreeMonoBold24pt7b.h>/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
|
|
|
|
|
#include <GxIO/GxIO.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(ESP32)
|
|
|
|
|
|
|
|
|
|
// for SPI pin definitions see e.g.:
|
|
|
|
|
// C:\Users\xxx\Documents\Arduino\hardware\espressif\esp32\variants\lolin32\pins_arduino.h
|
|
|
|
|
|
|
|
|
|
GxIO_Class io(SPI, /*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16); // arbitrary selection of 17, 16
|
|
|
|
|
GxEPD_Class display(io, /*RST=*/ 16, /*BUSY=*/ 4); // arbitrary selection of (16), 4
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
// for SPI pin definitions see e.g.:
|
|
|
|
|
// C:\Users\xxx\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.6.21\variants\standard\pins_arduino.h
|
|
|
|
|
|
|
|
|
|
GxIO_Class io(SPI, /*CS=*/ SS, /*DC=*/ 8, /*RST=*/ 9); // arbitrary selection of 8, 9 selected for default of GxEPD_Class
|
|
|
|
|
GxEPD_Class display(io, /*RST=*/ 9, /*BUSY=*/ 7); // default selection of (9), 7
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
float getObservationValue (int key)
|
|
|
|
|
{
|
|
|
|
|
return lastObservation[key];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////
|
|
|
|
|
///COMMUNICATION///
|
|
|
|
|
//////////////////
|
|
|
|
|
//Structure example to receive data
|
|
|
|
|
//Must match the sender structure
|
|
|
|
|
// This is the main loop of the program. It is ran whenever the board
|
|
|
|
|
// receives an observation.
|
|
|
|
|
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len)
|
|
|
|
|
{
|
|
|
|
|
Serial.println("received data");
|
|
|
|
|
clearDisplay();
|
|
|
|
|
display.println("Received an observation:");
|
|
|
|
|
memcpy(&lastObservation, incomingData, sizeof(lastObservation));
|
|
|
|
|
for(int i=0; i < featureCount; i++) {
|
|
|
|
|
//lastObservation[i] = *incomingData[i];
|
|
|
|
|
Serial.println(lastObservation[i]);
|
|
|
|
|
display.println(lastObservation[i]);
|
|
|
|
|
}
|
|
|
|
|
display.update();
|
|
|
|
|
delay(10 * 1000);
|
|
|
|
|
classify();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void clearDisplay (){
|
|
|
|
|
display.fillScreen(GxEPD_WHITE);
|
|
|
|
|
display.setTextColor(GxEPD_BLACK);
|
|
|
|
|
display.setFont(&FreeSans12pt7b);
|
|
|
|
|
display.setCursor(0, verticalOffset);
|
|
|
|
|
// display.update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mightPrintUnease () {
|
|
|
|
|
// Serial.println(random(2));/
|
|
|
|
|
// Serial.println(random(2));/
|
|
|
|
|
if (random(3) < 2) {
|
|
|
|
|
clearDisplay();
|
|
|
|
|
display.fillScreen(GxEPD_BLACK);
|
|
|
|
|
display.setTextColor(GxEPD_WHITE);
|
|
|
|
|
display.setFont(&FreeSansOblique12pt7b);
|
|
|
|
|
Serial.println("Printing an unease.");
|
|
|
|
|
// display.println(tracesOfUnease[random(t/raceCount)]);
|
|
|
|
|
display.update();
|
|
|
|
|
display.fillScreen(GxEPD_WHITE);
|
|
|
|
|
display.setTextColor(GxEPD_BLACK);
|
|
|
|
|
display.setFont(&FreeSans12pt7b);
|
|
|
|
|
delay(15 * 1000);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Consider a given value, feature number and threshold.
|
|
|
|
|
// If the value is lower than the threshold, answer yes
|
|
|
|
|
// otherwise answer no.
|
|
|
|
|
//
|
|
|
|
|
// Once every three calls a trace of unease will be printed
|
|
|
|
|
bool consider(float value, int feature, float threshold)
|
|
|
|
|
{
|
|
|
|
|
//mightPrintUnease();
|
|
|
|
|
clearDisplay();
|
|
|
|
|
Serial.println("Printing consideration");
|
|
|
|
|
clearDisplay();
|
|
|
|
|
Serial.println(considerationTraces);
|
|
|
|
|
display.println(considerationTraces);
|
|
|
|
|
// display.print("Step ");
|
|
|
|
|
// display.print(considerationStep);
|
|
|
|
|
display.print(".\nConsidering fea-\nture ");
|
|
|
|
|
display.print(feature);
|
|
|
|
|
display.print(", is it smaller\nthan ");
|
|
|
|
|
display.print(threshold);
|
|
|
|
|
display.print("?\n");
|
|
|
|
|
display.update();
|
|
|
|
|
delay(10 * 1000);
|
|
|
|
|
considerationStep = considerationStep + 1;
|
|
|
|
|
if (value < threshold) {
|
|
|
|
|
|
|
|
|
|
display.println("Yes. Going left.");
|
|
|
|
|
considerationTraces.concat(considerationStep);
|
|
|
|
|
considerationTraces.concat(": L ");
|
|
|
|
|
display.update();
|
|
|
|
|
delay(10 * 1000);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
display.println("No. Going right.");
|
|
|
|
|
considerationTraces.concat(considerationStep);
|
|
|
|
|
considerationTraces.concat(": R ");
|
|
|
|
|
display.update();
|
|
|
|
|
delay(10 * 1000);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Print the forwarded unease and consider the given value,
|
|
|
|
|
// feature number and threshold. If the value is lower than the threshold,
|
|
|
|
|
// return true otherwise false.
|
|
|
|
|
bool considerWithUnease(const char *unease, float value, int feature, float threshold)
|
|
|
|
|
{
|
|
|
|
|
Serial.println("Printing unease");
|
|
|
|
|
clearDisplay();
|
|
|
|
|
Serial.println(unease);
|
|
|
|
|
display.println(unease); // Test whether it's * ?
|
|
|
|
|
display.update();
|
|
|
|
|
delay(20 * 1000);
|
|
|
|
|
|
|
|
|
|
if (value < threshold) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void classify ()
|
|
|
|
|
{
|
|
|
|
|
considerationStep = 0;
|
|
|
|
|
considerationTraces = String();
|
|
|
|
|
Serial.println("Starting classification");
|
|
|
|
|
if (random(3) == 0) {
|
|
|
|
|
treeOfUnease.traverse(&getObservationValue, &considerWithUnease);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
answer=tree.predict(&getObservationValue, &consider);
|
|
|
|
|
clearDisplay();
|
|
|
|
|
// display.print("I say: ");
|
|
|
|
|
display.print(answerPrefix[random(answerPrefixLength)]);
|
|
|
|
|
display.print(answer);
|
|
|
|
|
display.update();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setup()
|
|
|
|
|
{
|
|
|
|
|
randomSeed(analogRead(26));
|
|
|
|
|
// Setup serial
|
|
|
|
|
Serial.begin(115200);
|
|
|
|
|
Serial.println();
|
|
|
|
|
Serial.println("setup");
|
|
|
|
|
display.init(115200); // enable diagnostic output on Serial
|
|
|
|
|
Serial.println("Starting...\n");
|
|
|
|
|
|
|
|
|
|
// Setup WiFi
|
|
|
|
|
// Set device as a Wi-Fi Station
|
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
|
|
|
// print our mac address
|
|
|
|
|
Serial.println(WiFi.macAddress());
|
|
|
|
|
// Init ESP-NOW
|
|
|
|
|
if (esp_now_init() != ESP_OK) {
|
|
|
|
|
Serial.println("Error initializing ESP-NOW");
|
|
|
|
|
for(;;) { delay(1); } // do not initialize wait forever
|
|
|
|
|
}
|
|
|
|
|
Serial.println("initialized ESP-NOW");
|
|
|
|
|
|
|
|
|
|
// First output to the world!
|
|
|
|
|
clearDisplay();
|
|
|
|
|
display.setRotation(2);
|
|
|
|
|
// display.println("Hello!");
|
|
|
|
|
display.print("Tree ");
|
|
|
|
|
display.print(treeNumber);
|
|
|
|
|
display.print("\n");
|
|
|
|
|
display.println("You can reach me at");
|
|
|
|
|
display.println(WiFi.macAddress());
|
|
|
|
|
display.update();
|
|
|
|
|
|
|
|
|
|
delay(1000);
|
|
|
|
|
|
|
|
|
|
// Register for a callback function that will be called when data is received
|
|
|
|
|
esp_now_register_recv_cb(OnDataRecv);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void loop()
|
|
|
|
|
{
|
|
|
|
|
delay(500);
|
|
|
|
|
// clearDisplay();
|
|
|
|
|
// if (dataReceived%2==0){
|
|
|
|
|
// Serial.println();
|
|
|
|
|
//// dataReceived_s= "whispers in my ears";
|
|
|
|
|
//// predicted= " an oak ";
|
|
|
|
|
// }
|
|
|
|
|
// else{
|
|
|
|
|
// Serial.println(clf.predict(irisSample, println, clear, delay));
|
|
|
|
|
//// dataReceived_s= "murmurations";
|
|
|
|
|
//// predicted= "an Iris";
|
|
|
|
|
// }
|
|
|
|
|
}
|