Evelyn ShenDarren Shen
Published

Little Free STEM Library

A smart STEM powered library that advocates for inclusivity for all kids and adolescents!

IntermediateWork in progress5 days129

Things used in this project

Hardware components

Mini Shed Little Free Library
×1
FireBeetle ESP32 IOT Microcontroller (Supports Wi-Fi & Bluetooth)
DFRobot FireBeetle ESP32 IOT Microcontroller (Supports Wi-Fi & Bluetooth)
×1
DFRobot 3.5” 480x320 TFT LCD
×1
Adafruit 3x4 Phone-style Matrix Keypad
×1
DFPlayer - A Mini MP3 Player
DFRobot DFPlayer - A Mini MP3 Player
×1
Gravity: Digital 5A Relay Module
DFRobot Gravity: Digital 5A Relay Module
×1
120W Portable Power Station
×1
Solar Panel Kit 20W 12V
×1
FFC 18 Pin 0.5mm Pitch 200mm Long (B Type)
×1
3 Watt 8 Ohm Single Cavity Mini Speaker
×1
I2C IO Expander Module
×1
DFRobot Ultrasonic Distance Sensor
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

LFL

Code

LFL

Arduino
Little Free STEM Library software
#include "DFRobot_GDL.h"
#include "Wire.h"
#include "I2CKeyPad.h"
#include "DFRobotDFPlayerMini.h"
#include "DFRobot_EnvironmentalSensor.h"


const int p_rows = 45;
const int p_columns = 30;
const int y_columns = 5;

static char p_2d [p_rows][p_columns] = {
{"George Washington"},		
{"John Adams"}, 			
{"Thomas Jefferson"}, 		
{"James Madison"},		
{"James Monroe"}, 		
{"John Quincy Adams"},		
{"Andrew Jackson"}, 		
{"Martin Van Buren"}, 		
{"William Henry Harrison"},	
{"John Tyler"}, 			
{"James Knox Polk"},		
{"Zachary Taylor"},		
{"Millard Fillmore"},		
{"Franklin Pierce"},		
{"James Buchanan"},		
{"Abraham Lincoln"},		
{"Andrew Johnson"},		
{"Ulysses S. Grant"}, 		
{"Rutherford B. Hayes"},		
{"James A. Garfield"},		
{"Chester Arthur"},		
{"Grover Cleveland"}, 		
{"Benjamin Harrison"},				
{"William McKinley"}, 		
{"Theodore Roosevelt"}, 		
{"William Howard Taft"},		
{"Woodrow Wilson"}, 		
{"Warren G. Harding"},		
{"Calvin Coolidge"},		
{"Herbert Hoover"},		
{"Franklin D. Roosevelt"},	
{"Harry S. Truman"},		
{"Dwight D. Eisenhower"}, 	
{"John F. Kennedy"},		
{"Lyndon B. Johnson"},		
{"Richard M. Nixon"}, 		
{"Gerald R. Ford"},		
{"Jimmy Carter"},		
{"Ronald Reagan"},		
{"George Bush"},			
{"William J. Clinton"}, 		
{"George W. Bush"}, 		
{"Barack Obama"}, 		
{"Donald J. Trump"},		
{"Joe Biden"}};

static char p_year [p_rows][y_columns] = {
"1789",  //{"George Washington"},		1 	
"1797",  //{"John Adams"}, 		 			2
"1801",  //{"Thomas Jefferson"}, 		3	
"1809",  //{"James Madison"},		 4
"1817",  //{"James Monroe"}, 			5
"1825",  //{"John Quincy Adams"},	6				
"1829",  //{"Andrew Jackson"}, 		7	
"1837",  //{"Martin Van Buren"}, 	8				
"1841",  //{"William Henry Harrison"}, 9				
"1841",  //{"John Tyler"}, 		 			10
"1845",  //{"James Knox Polk"},				11	
"1849",  //{"Zachary Taylor"},					12
"1850",  //{"Millard Fillmore"},					13
"1853",  //{"Franklin Pierce"},					14
"1857",  //{"James Buchanan"},					15
"1861",  //{"Abraham Lincoln"},			16
"1865",  //{"Andrew Johnson"},			17		
"1869",  //{"Ulysses S. Grant"}, 		 
"1877",  //{"Rutherford B. Hayes"},	 			
"1881",  //{"James A. Garfield"},					
"1881",  //{"Chester Arthur"},					
"1885",  //{"Grover Cleveland"}, 					
"1889",  //{"Benjamin Harrison"},								
"1897",  //{"William McKinley"}, 			
"1901",  //{"Theodore Roosevelt"}, 	 	
"1909",  //{"William Howard Taft"},	 			
"1913",  //{"Woodrow Wilson"}, 			
"1921",  //{"Warren G. Harding"},					
"1923",  //{"Calvin Coolidge"},		 
"1929",  //{"Herbert Hoover"},					
"1933",  //{"Franklin D. Roosevelt"},	 
"1945",  //{"Harry S. Truman"},			
"1953",  //{"Dwight D. Eisenhower"}, 		
"1961",  //{"John F. Kennedy"},					
"1963",  //{"Lyndon B. Johnson"},		 
"1969",  //{"Richard M. Nixon"}, 			
"1974",  //{"Gerald R. Ford"},					
"1977",  //{"Jimmy Carter"},					
"1981",  //{"Ronald Reagan"},			
"1989",  //{"George H. W. Bush"},		 			
"1993",  //{"William J. Clinton"}, 	 	
"2001",  //{"George W. Bush"}, 			
"2009",  //{"Barack Obama"}, 			
"2017",  //{"Donald J. Trump"},					
"2021"   //{"Joe Biden"}
};

//folder 01
//001 - welcome
//002 - unlock
//003 - what year_did
//004 - become_pre
//005 - example
//006 - press any key to start
//folder 02
//001 to 009
//folder 03
//001gw ... 0045jb


#define ESP32

 //LCD SCREEN   
/*M0*/
#if defined ARDUINO_SAM_ZERO
#define TFT_DC  7
#define TFT_CS  5
#define TFT_RST 6
/*ESP32 and ESP8266*/
#elif defined(ESP32) || defined(ESP8266)
#define TFT_DC  D2
#define TFT_CS  D6
#define TFT_RST D3
/*AVR series mainboard*/
#else
#define TFT_DC  2
#define TFT_CS  3
#define TFT_RST 4
#endif

/**
* @brief Constructor Constructor of hardware SPI communication
* @param dc Command/data line pin for SPI communication
* @param cs Chip select pin for SPI communication
* @param rst reset pin of the screen
*/

//DFRobot_ST7789_240x240_HW_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);
//DFRobot_ST7789_240x320_HW_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);
//DFRobot_ILI9341_240x320_HW_SPI  screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);
DFRobot_ILI9488_320x480_HW_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);

/* M0 mainboard DMA transfer */
//DFRobot_ST7789_240x240_DMA_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);
//DFRobot_ST7789_240x320_DMA_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);
//DFRobot_ILI9341_240x320_DMA_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);
//DFRobot_ILI9488_320x480_DMA_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);

/*
*User-selectable macro definition color
*COLOR_RGB565_BLACK   COLOR_RGB565_NAVY    COLOR_RGB565_DGREEN   COLOR_RGB565_DCYAN 
*COLOR_RGB565_MAROON  COLOR_RGB565_PURPLE  COLOR_RGB565_OLIVE    COLOR_RGB565_LGRAY     
*COLOR_RGB565_DGRAY   COLOR_RGB565_BLUE    COLOR_RGB565_GREEN    COLOR_RGB565_CYAN  
*COLOR_RGB565_RED     COLOR_RGB565_MAGENTA COLOR_RGB565_YELLOW   COLOR_RGB565_ORANGE           
*COLOR_RGB565_WHITE   
*/

//MP3 UART
#if (defined(ARDUINO_AVR_UNO) || defined(ESP8266))   // Using a soft serial port
  #include <SoftwareSerial.h>
  SoftwareSerial softSerial(/*rx =*/4, /*tx =*/5);
  #define FPSerial softSerial
#else
  #define FPSerial Serial2 //TX - Pin17 D10; RX - Pin16 D11
#endif

DFRobotDFPlayerMini myDFPlayer;

//I2C
#define I2C_KEYPAD_4x3            43
const uint8_t KEYPAD_ADDRESS = 0x20;

I2CKeyPad keyPad(KEYPAD_ADDRESS);

uint32_t start, stop;
uint32_t lastKeyPressed = 0;

bool no_print1 = true;
bool no_print2 = true;
bool no_print3 = true;
bool no_print4 = true;

DFRobot_EnvironmentalSensor environment(/*addr = */SEN050X_DEFAULT_DEVICE_ADDRESS, /*pWire = */&Wire);

// defines variables
long duration;
int distance;

//#define bluePin D7
//#define redPin  D2
//#define trigPin D5
//#define echoPin D12
#define mp3txPin D10 //17
#define mp3rxPin D11 //16
#define lockPin D7

#define  MAX_RANG      (520)//the max measurement vaule of the module is 520cm(a little bit longer than  effective max range)
#define  ADC_SOLUTION      (1023.0)//ADC accuracy of Arduino UNO is 10bit
#define  sensityPin A0    // select the input pin 
float dist_t, sensity_t;

void setup() {       
  //Serial.begin(115200);
  Serial.begin(9600);
  Serial.println("start");
  screen.begin();

  //Set font size to 4, font range 1-4
  screen.setTextSize(2.5);
        
  //Set screen color 
  screen.fillScreen(COLOR_RGB565_BLACK);
  screen.setFont(&FreeSansBold9pt7b);//Set font to FreeMono12pt7b
  screen.setRotation(3);
  screen.setCursor(/*x=*/0,/*y=*/30);
        
  //Set text color 
  screen.setTextColor(COLOR_RGB565_YELLOW);
        
  //Set to text auto-wrap mode, true=Auto-wrap, false=No auto-wrap
  screen.setTextWrap(true);
  Serial.println("start done");
        
  #if (defined ESP32)
    FPSerial.begin(9600, SERIAL_8N1, /*rx =*/mp3rxPin, /*tx =*/mp3txPin);
  #else
    FPSerial.begin(9600);
  #endif

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(FPSerial, /*isACK = */false, /*doReset = */true)) {  //Use serial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
  }
  else {
    Serial.println(F("DFPlayer Mini online."));
  }

  myDFPlayer.volume(20);  //Set volume value. From 0 to 30
  //myDFPlayer.loop(1);  //Play the first mp3Wire.begin();

  //I2C keypad
  Wire.setClock(400000);
  if (keyPad.begin() == false)
  {
    Serial.println("\nERROR: cannot communicate to keypad.\nPlease reboot.\n");
    while(1);
  }

  keyPad.setKeyPadMode(I2C_KEYPAD_4x3);

  //pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  //pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  pinMode(sensityPin, INPUT);
  pinMode(lockPin, OUTPUT); //set Lock
 
}

void loop(){
  char keys[] = "123A456B789C*0#DNF";  // N = NoKey, F = Fail   
  char keyin[5];
  char *pos;
  uint8_t cnt;
  unsigned long timer = millis();
  int term = random(p_rows);
  int color = COLOR_RGB565_LGRAY;
  int song = 0;
  bool empty = false;

  screen.fillScreen(COLOR_RGB565_BLACK);
  //screen.drawLine(screen.width, 30, 0, 30, color);

  //1. Print welcome message
  while (!keyPad.isPressed()) {
    //screen.fillScreen(COLOR_RGB565_BLACK);
    //if(millis() - timer > 20000) {
    //  timer = millis();
      //myDFPlayer.next();
      //myDFPlayer.play(1);
      //myDFPlayer.play(56);
      //delay(10);
    //}
    //myDFPlayer.playLargeFolder(2, 999);
    //myDFPlayer.playFolder(1, 1);

    //for (int cnt = 1; cnt <= 10; cnt++) {
      //screen.setCursor(/*x=*/0,/*y=*/35);
      //screen.setTextColor(COLOR_RGB565_YELLOW);
      //screen.println(cnt);
      //screen.println();
    //  myDFPlayer.playFolder(2, cnt);
    //  Serial.print(cnt);
    //  delay(3000);
    //}
    //myDFPlayer.play(1);
    screen.setCursor(/*x=*/0,/*y=*/50);
    screen.setTextColor(COLOR_RGB565_YELLOW);
    screen.println("WELCOME TO THE LITTLE FREE STEM LIBRARY");
    //myDFPlayer.playFolder(1, 1);
    if(millis() - timer > 3000) {
      timer = millis();
      if (song == 0) {
        myDFPlayer.playFolder(1, 1);
        song = 1;
      } else {
        myDFPlayer.playFolder(1, 6);
        song = 0;
      }
    }
    //delay(3000);
    screen.println();
    screen.setTextColor(color);
    //screen.setTextWrap(true);
    //screen.setTextSize(1);
    screen.println("Press any key to start");
    //myDFPlayer.playFolder(1, 6);
    //delay(3000);
  } 
  
  //screen.fillScreen(COLOR_RGB565_BLACK);
  //screen.setCursor(/*x=*/0,/*y=*/25);
  //screen.println("Let's start");
  //myDFPlayer.next();  //Play next mp3 every 3 second.
  
  screen.fillScreen(COLOR_RGB565_BLACK);
  screen.setCursor(/*x=*/0,/*y=*/50);
  screen.setTextColor(COLOR_RGB565_LGRAY);
  screen.println("please answer the following question to unlock");
  myDFPlayer.playFolder(1, 2);
  delay(3000);
  //myDFPlayer.next();  //Play next mp3 every 3 second.
  //myDFPlayer.play(57);

  screen.fillScreen(COLOR_RGB565_BLACK);
  screen.setTextColor(COLOR_RGB565_GREEN);
  screen.setCursor(/*x=*/0,/*y=*/30);
  //screen.println(term);
  screen.println("In which year did ");
  myDFPlayer.playFolder(1, 3);
  delay(2000);
  screen.setTextColor(COLOR_RGB565_LGRAY);
  screen.println(p_2d[term]);
  //for (int i = 1; i <=46; i++){
  //  screen.println(i);
  //  myDFPlayer.playFolder(3, i);
  //  delay(3000);
  //}
  myDFPlayer.playFolder(3, (term+1));
  delay(2000);
  screen.setTextColor(COLOR_RGB565_GREEN);
  screen.print("become President?");
  myDFPlayer.playFolder(1, 4);
  delay(2000);
  Serial.println(p_year[term]);
  screen.println();
  screen.println();
  screen.setTextColor(COLOR_RGB565_CYAN);
  screen.println("Please enter the year and the '#' sign at the end, ex: 1948#");
  myDFPlayer.playFolder(1, 5);
  
  //delay(6000);
  char buf[5];
  int result = readKeyPadUntil('#', buf, 5, 100000);
  if (result == 0)
  {
    Serial.println(buf);
    //screen.fillScreen(COLOR_RGB565_BLACK);
    screen.fillScreen(COLOR_RGB565_BLACK);
    screen.setCursor(/*x=*/0,/*y=*/50);
    screen.println(buf);
    //if(strcmp(buf, "1234") == 0) {
    if(strcmp(buf, p_year[term]) == 0) {
      //while (Serial.available ()==0){}
      screen.setTextColor(COLOR_RGB565_GREEN);
      myDFPlayer.playFolder(1, 7);
      screen.println("YEAH!!! CORRECT!!!");
      screen.println("UNLOCKED!!");
      //unlock
      digitalWrite(lockPin, HIGH);
      delay(20000);
      digitalWrite(lockPin, LOW);
      //myDFPlayer.playFolder(1, 6); //please close the door once you are done
      delay(30000);
    } else {
      screen.setTextColor(COLOR_RGB565_RED);
      myDFPlayer.playFolder(1, 8);
      screen.print("Wrong!! Please try again!!");
      delay(2000);
    }

    //adhoc codes
    //check Ambient light range: 0~120 klx
    //Print the data obtained from sensor
    Serial.println("-------------------------------");
    Serial.print("Temp: ");
    Serial.print(environment.getTemperature(TEMP_F));
    Serial.println(" ℉");
    Serial.print("LuminousIntensity: ");
    Serial.println(environment.getLuminousIntensity());
    Serial.println("-------------------------------");

    //check if library is empty
    // read the value from the sensor:
    sensity_t = analogRead(sensityPin);
    dist_t = sensity_t * MAX_RANG  / ADC_SOLUTION;//
    Serial.print(dist_t,0);
    Serial.println("cm");
    if (dist_t > 24) {
      empty = true;
      myDFPlayer.playFolder(1, 9);
      screen.fillScreen(COLOR_RGB565_BLACK);
      screen.setCursor(/*x=*/0,/*y=*/50);
      screen.setTextColor(COLOR_RGB565_YELLOW);  
      screen.println("Refill!! Library is empty!!");
      Serial.println("Library is empty");
      delay(5000);
    }
    else {
      empty = false;
    }
  }
  if (result == -1)
  {
    Serial.print("FAILURE: ");
    Serial.println(buf);
  }
  if (result == -2)
  {
    Serial.print("TIMEOUT: ");
    Serial.println(buf);
  }
  if (result == -3)
  {
    Serial.print("OVERFLW: ");
    Serial.println(buf);
  }
  //delay(1000);
}

//
// until   = end character
// buffer  = buffer to fill
// length  = length of buffer (including '\0'
// timeout = timeout in milliseconds
// returns 0 = success
//        -1 = keyPad fail
//        -2 = timeout
//        -3 = buffer overflow
int readKeyPadUntil(char until, char * buffer, uint8_t length, uint16_t timeout)
{
  char keymap[19] = "123A456B789C*0#DNF";  // ... NoKey  Fail }  
  uint8_t bufferIndex = 0;
  uint32_t start = millis();

  // empty buffer
  buffer[bufferIndex] = 0;

  while (true)
  {
    // while no key is pressed wait
    while (keymap[keyPad.getKey()] == 'N')
    {
      delay(1);
      yield();
      if (millis() - start > timeout) return -2;
    }

    // get the key pressed
    uint8_t raw = keyPad.getLastKey();

    // process key pressed
    uint8_t key = keymap[raw];

    // handle end conditions
    if ( key == until) return 0;
    if ( key == 'F') return -1;    // failed to read;
    if (bufferIndex == length) return -3;

    // add key to buffer
    buffer[bufferIndex++] = key;
    buffer[bufferIndex] = 0;

    // while key is pressed wait
    while (keymap[keyPad.getKey()] == key)
    {
      yield();
      if (millis() - start > timeout) return -2;
    }
  }
}

Credits

Evelyn Shen

Evelyn Shen

2 projects • 2 followers
i love coding! coding is awesome!
Darren Shen

Darren Shen

4 projects • 3 followers
Pro Coder

Comments