Back to Parent

// PIN Number Documentation
// Acoustic Servo D2
// Interface LED Strip D6
// Interface LED Ring D7
// Central LED PWM Controller D9

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>

#if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32
  #define TFT_CS         14
  #define TFT_RST        15
  #define TFT_DC         32

#elif defined(ESP8266)
  #define TFT_CS         4
  #define TFT_RST        16
  #define TFT_DC         5

#else
  // For the breakout board, you can use any 2 or 3 pins.
  // These pins will also work for the 1.8" TFT shield.
  #define TFT_CS        10
  #define TFT_RST        9 // Or set to -1 and connect to Arduino RESET pin
  #define TFT_DC         8
#endif

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

#include <Adafruit_NeoPixel.h>
#define LEDSTRIP_PIN    6
#define LEDSTRIP_CNT  16

#define LEDRING_PIN    7
#define LEDRING_CNT  16

// Create an instance of the Adafruit_NeoPixel class
Adafruit_NeoPixel ledstrip(LEDSTRIP_CNT, LEDSTRIP_PIN, NEO_GRB + NEO_KHZ800);
// Create an instance of the Adafruit_NeoPixel class
Adafruit_NeoPixel ledring(LEDRING_CNT, LEDRING_PIN, NEO_GRB + NEO_KHZ800);


#include <Wire.h>
#include <math.h>

#include "Adafruit_VCNL4010.h"
Adafruit_VCNL4010 vcnl;
unsigned long previousMillis_BRKT = 0;
const unsigned long interval_BRKT = 1000;
String BRKT_STATUS = "false";

// Define LD24AJTA device address and brightness register address
#define LD24AJTA_ADDRESS 0x2A
#define BRIGHTNESS_REGISTER 0x00
// Define Central LED PWM pin
#define CTLED_PIN 9


#include <Servo.h>
int SERVO_PIN = 2; // Servo motor 1 pin
Servo SERVO1; // Servo motor 1 object

void setup() {
  Serial.begin(9600);
  Wire.begin();  // Initialize I2C communication
  pinMode(CTLED_PIN, OUTPUT);  // Set LED pin as output

  // put your setup code here, to run once:
  // initaite VCNL proximity sensor 
  vcnl.begin();


  //LED strip initiation
  ledstrip.begin();           // Initialize the LED strip
  ledstrip.setBrightness(100);
  ledstrip.show();            // Turn all LEDs off initially

  //LED ring initiation
  ledring.begin();           // Initialize the LED strip
  ledring.show();            // Turn all LEDs off initially
  ledring.setBrightness(75);
  // Set overall brightness to 50 (out of 255)
  for(int i=0; i< ledring.numPixels(); i++) {
    ledring.setPixelColor(i, 255, 0, 255 );
    ledring.setBrightness(75);
		ledring.show();
  }

  //central LED beginning brightness:
  setBrightness(45);

  //Setup Servo
  SERVO1.attach(SERVO_PIN); // Attach servo motor 1 to D2

  tft.init(172, 320);
  tft.fillScreen(ST77XX_BLACK);
  tft.setRotation(3); // Set screen orientation to landscape
  
}

void loop() {
  // check for mobile phone bracket status every 1s
  unsigned long miningTime = getBracketStatusTime();
  Serial.print("Total miningTime:");
  Serial.println(miningTime);
  bracketStatus();
  updatePrompt( miningTime);
  // if bracket is detected, call mining function and set servo speed
  if (BRKT_STATUS == "true") {
    ledstripMINING(5, 100);
    setBrightness(255);
    setServoSpeed(miningTime);
  } else {
    ledstripOFF();
    setBrightness(45);
    if (miningTime == 0) {
      SERVO1.write(90); // Stop the servo motor
    }
  }
}


void ledstripMINING(int numLEDs, int delayTime) {
  static unsigned long prevTime = 0; // Stores the previous time when an LED was updated
  static int currentLED = 0; // Stores the index of the current LED being updated
  // Only update the LEDs after the specified delay time has passed
  if (millis() - prevTime >= delayTime) {
    // Turn off all LEDs initially
    for (int i = 0; i < LEDSTRIP_CNT; i++) {
      ledstrip.setPixelColor(i, 0, 0, 0);
    }
    // Turn on the numLEDs LEDs starting from currentLED
    for (int i = currentLED; i < currentLED + numLEDs; i++) {
      int pixel = i % LEDSTRIP_CNT; // Make sure the pixel index wraps around if it exceeds the strip length
      ledstrip.setPixelColor(pixel, 255, 0, 255); // Set the pixel color to red
    }
    ledstrip.show(); // Update the strip with the new colors
    // Update the currentLED index for the next loop
    currentLED++;
    if (currentLED >= LEDSTRIP_CNT) {
      currentLED = 0;
    }
    // Store the current time for the next loop
    prevTime = millis();
  }
}


void ledstripOFF() {
    // turn off all LEDs on the strip
    for (int i = 0; i < LEDSTRIP_CNT; i++) {
      ledstrip.setPixelColor(i, 0, 0, 0);
    }
    ledstrip.show(); // update the strip with the new colors
} 


void LED_FALSE(int times, int interval) {
  int i = 0;
  
  while (i < times) {
    ledstrip.fill(ledstrip.Color(255, 0, 0));   // Set all LEDs to white
    ledstrip.show();   // Turn on all LEDs
    unsigned long startTime = millis();
    while ((millis() - startTime) < interval) {}   // Wait for the specified interval
    ledstrip.clear();   // Turn off all LEDs
    ledstrip.show();   // Update the LED strip to turn off all LEDs
    startTime = millis();
    while ((millis() - startTime) < interval) {}   // Wait for the specified interval
    i++;
  }
}



//check for mobile phone bracket status every 1s.
void bracketStatus() {
  unsigned long currentMillis_BRKT = millis();
  if (currentMillis_BRKT - previousMillis_BRKT >= interval_BRKT) {
    int proximityValue = vcnl.readProximity();
    int proximityValue_mapped = (map(proximityValue, 65535, 2156, 0, 100));
    Serial.print("Proximity: ");
    Serial.println(proximityValue_mapped);
    if (proximityValue_mapped <= 90) { BRKT_STATUS = "true"; } 
    else { BRKT_STATUS = "false";}
    Serial.print("BRKT_STATUS: ");
    Serial.println(BRKT_STATUS);
    previousMillis_BRKT = currentMillis_BRKT;
  }
}

//Set central LED brightness using PWM controller
void setBrightness(byte brightness) {
  // Send brightness value to LD24AJTA controller
  Wire.beginTransmission(LD24AJTA_ADDRESS);
  Wire.write(BRIGHTNESS_REGISTER);
  Wire.write(brightness);
  Wire.endTransmission();
  // Set LED brightness using PWM
  analogWrite(CTLED_PIN, brightness);
}

unsigned long bracketStatusStartTime = 0;
unsigned long bracketStatusTotalTime = 0;

unsigned long getBracketStatusTime() {
  static unsigned long bracketStatusTotalTime = 0;
  static unsigned long bracketStatusStartTime = 0;
  unsigned long currentMillis_BRKT = millis();
  
  if (BRKT_STATUS == "true") {
    if (bracketStatusStartTime == 0) {
      bracketStatusStartTime = currentMillis_BRKT;
    }
    bracketStatusTotalTime += currentMillis_BRKT - bracketStatusStartTime;
    bracketStatusStartTime = currentMillis_BRKT; // reset start time to current time
  } else {
    bracketStatusStartTime = 0;
    bracketStatusTotalTime = 0; // reset total time when bracket status is false
  }
  return bracketStatusTotalTime;
}


void setServoSpeed(unsigned long miningTime) {
  static unsigned long lastUpdateTime = 0;
  static int servoSpeed = 90;
  
  if (millis() - lastUpdateTime > 1000) { // Update every 100ms
    if (miningTime == 0) {
      SERVO1.write(90);
      // Set servo speed to 90 if totalMiningTime is 0
    } else {

      int targetSpeed = constrain(map(miningTime, 6000, 15000, 90, 180), 90, 180);
       // Only update if the target speed has changed
        if (targetSpeed > servoSpeed) 
          {
          servoSpeed++; // Accelerate servo
          } 
        else 
          {
          servoSpeed = 90; // Decelerate serv
          }
    }
    SERVO1.write(servoSpeed);
    Serial.print("Current Servo Speed:");
    Serial.println(servoSpeed);
    lastUpdateTime = millis();
    return servoSpeed;
  }
}

void tftDrawtext(char *text, int line_number) {

  tft.setTextSize(3);
  tft.setCursor(0, line_number); // Set cursor position to x=0, y=80
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextWrap(true);
  tft.print(text);
}

unsigned long lastUpdateTime_tft = 0;
const unsigned long updateInterval_tft = 3000; // 3 seconds

void updatePrompt(int miningTime) {
  int batterylife = map(miningTime, 0, 45000, 100, 60);
  if (millis() - lastUpdateTime_tft >= updateInterval_tft) {
    if (miningTime == 0) {
      tft.fillScreen(ST77XX_BLACK);
      tftDrawtext("Place your mobile phone for illumination", 50);
    } else if ((miningTime < 10000) && (miningTime > 0)) {
      tft.fillScreen(ST77XX_BLACK);
      tftDrawtext("Illumination turned ON!  Enjoy!!!", 60);
    } else if ((miningTime < 45000) && (miningTime > 10000)) {
      tft.fillScreen(ST77XX_BLACK);
      tftDrawtext("Remaining Battery Life (%): ", 50);
      tftDrawtext(String(batterylife).c_str(), 100);
    } else  {
      setBrightness(45);
      tft.fillScreen(ST77XX_BLACK);
      tftDrawtext("Free illumination limit reached. Upgrade to premium or replace mobile phone", 30);
      LED_FALSE(10, 500);
      
      
    }
    lastUpdateTime_tft = millis();
  }
}
Click to Expand

Content Rating

Is this a good/useful/informative piece of content to include in the project? Have your say!

0