// from the manual
#define FASTLED_ESP32_SPI true
#define FASTLED_RMT_MAX_CHANNELS 1
#define FASTLED_INTERNAL
#include <ESP32Servo.h> //This library is used for controlling servo motors with the ESP32.
#include <FastLED.h> // It's a library for controlling addressable LEDs (such as WS2812) efficiently.
// from the manual
// Recommended pins include 2,4,12-19,21-23,25-27,32-33
int servo_Pins[] = { 12, 13, 14, 15, 18, 19, 21, 22, 23, 27, 32, 33, 2, 4};
#define LED_PIN 5 // Pin connected to the LED strip
#define NUM_SERVOS 14
const int NUM_LEDS_PER = 7;
const int NUM_LEDS = NUM_SERVOS * NUM_LEDS_PER ;
const int number_Commands = 8;
const char Names[number_Commands][20] = {
"happy",
"content",
"anxious",
"sad",
"irritable",
"stressed",
"miserable",
"off"
};
// set of colors
const CRGB colors[number_Commands]={
CRGB(178, 223, 198),
CRGB(254, 221, 196),
CRGB(255, 171, 215),
CRGB(193, 239, 251),
CRGB(255, 172, 174),
CRGB(247, 3, 3),
CRGB(228, 199, 247),
CRGB(0, 0, 0)
};
const byte numChars = 32; // largest message
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;
char strNum ;
int number_of_received_characters = 0;
Servo flower_servos[NUM_SERVOS];
// from the manual
// Published values for SG90 servos; adjust if needed
int minUs = 1000;
int maxUs = 2000;
CRGB leds[NUM_LEDS];
// https://forum.arduino.cc/t/serial-input-basics-updated/382007
void recvWithEndMarker() {
static byte ndx = 0;
char endMarker = '\n';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
// receivedChars[ndx] = '\0'; // terminate the string
number_of_received_characters=ndx;
ndx = 0;
newData = true;
}
}
}
void processNewData() {
if (newData == true) {
bool input_error = false;
if ( number_of_received_characters < 3)
{
Serial.println(" error in data validations - not enough characters");
input_error = true;
}
String StrNum = String(receivedChars[0]) + receivedChars[1] + "\0";
int flower_number=StrNum.toInt();
int command_number = -1;
if ( StrNum.toInt() == 0 )
{
Serial.println(" error in data validations - flower number incorrect");
input_error = true;
}
// get the last parts
char* pmn = receivedChars + 2*sizeof(receivedChars[0]);
for (int i = 0; i < number_Commands ; i++) {
if (strcmp(pmn , Names[i]) == 0)
command_number=i;
}
Serial.print(" Complete Code received ");
Serial.print(receivedChars);
Serial.print(" \t The flower number");
Serial.println(flower_number);
Serial.print(" The command=");
Serial.println(pmn);
Serial.print(" The command number=");
Serial.println(command_number);
newData = false;
memset(receivedChars, 0, 32); // clear memory
flower_color_set(flower_number,command_number);
}
}
void flower_color_set( int flower, int command_number)
{
int led_start=flower * NUM_LEDS_PER ;
int led_stop=led_start + NUM_LEDS_PER ;
if (command_number < NUM_LEDS_PER )
{
for ( int y=led_start; y<led_stop;y++)
{
leds[y] = colors[command_number];
}
flower_servos[flower].write(180);
}
else
{
for ( int y=led_start; y<led_stop;y++)
{
leds[y] = colors[7];
}
flower_servos[flower].write(0);
}
FastLED.show();
}
void test_start()
{
for (int x=0; x < NUM_SERVOS;x++)
{
flower_color_set(x,5);
}
delay(1000);
for (int x= 0 ; x<14;x++)
{
flower_color_set(x,random(0,NUM_LEDS_PER ));
delay(40);
}
delay(500);
for (int x=0; x < NUM_SERVOS;x++)
{
flower_color_set(x,NUM_LEDS_PER );
}
delay(1000);
}
void setup() {
Serial.begin(115200);
// from the manual
// Allow allocation of all timers
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
for ( int i = 0; i < NUM_SERVOS; i++)
{
flower_servos[i].setPeriodHertz(50); // Standard 50hz servo
flower_servos[i].attach(servo_Pins[i], minUs, maxUs);
flower_servos[i].write(0);
}
// Setup WS2812 LED strip
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
test_start(); // dumb test
Serial.println("Started - enter flower number as 2 digit number then command ");
}
void loop() {
// real serial input checking - not dodgy until
recvWithEndMarker();
processNewData();
}