// PCB Tree code for Fabacademy final project // Jesal Mehta, 2023 // // // tx_rx() function after Robert Hart Mar 2019, modified by Adrián Torres Omaña, 2023 (single touch pad) // this version is for 4 touchpads, logic differences // step sensor activation triggers various lighting patterns over the tree #include #define PIN 3 #define NUMPIXELS 10 Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); #define DELAYVAL 500 //to capture txrx measurement result long res1; long res2; long res3; long res4; //int analog_pin = 27; // GPIO 27 of the XIA0 RP2040 int a1_pin = 26; // GPIO 26 of the XIA0 RP2040 int a2_pin = 27; // GPIO 27 of the XIA0 RP2040 int a3_pin = 28; // GPIO 28 of the XIA0 RP2040 int a4_pin = 29; // GPIO 29 of the XIA0 RP2040 int tx_pin = 6; void setup() { pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED) pinMode(tx_pin, OUTPUT); //Pin 2 provides the voltage step Serial.begin(115200); } void tx_rx() { //function to measure relative differences, core of the input side of the program int read_high1; int read_high2; int read_high3; int read_high4; int read_low1; int read_low2; int read_low3; int read_low4; int diff1; int diff2; int diff3; int diff4; long int sum1; long int sum2; long int sum3; long int sum4; int N_samples = 500; //Number of samples - larger = better but slower sum1 = 0; sum2 = 0; sum3 = 0; sum4 = 0; for (int i = 0; i < N_samples; i++) { digitalWrite(tx_pin, HIGH); //Step the voltage high on conductor 1. read_high1 = analogRead(a1_pin); //Measure response of conductor 2. read_high2 = analogRead(a2_pin); read_high3 = analogRead(a3_pin); read_high4 = analogRead(a4_pin); delayMicroseconds(100); //Delay to reach steady state. digitalWrite(tx_pin, LOW); //Step the voltage to zero on conductor 1. read_low1 = analogRead(a1_pin); //Measure response of conductor 2. read_low2 = analogRead(a2_pin); read_low3 = analogRead(a3_pin); read_low4 = analogRead(a4_pin); diff1 = read_high1 - read_low1; //desired answer is the difference between high and low. diff2 = read_high2 - read_low2; diff3 = read_high3 - read_low3; diff4 = read_high4 - read_low4; sum1 += diff1; //Sums up N_samples of these measurements. sum2 += diff2; sum3 += diff3; sum4 += diff4; } res1 = sum1; res2 = sum2; res3 = sum3; res4 = sum4; //single touch version returns the variable, however, with 4 results, global variables are a better option return; } void loop() { pixels.clear(); // Set all pixel colors to 'off' tx_rx(); // res1 = map(res1, 0, 20000, 0, 1024); // res2 = map(res2, 0, 30000, 0, 1024); // res3 = map(res3, 0, 40000, 0, 1024); // res4 = map(res4, 0, 65000, 0, 1024); // res1 = map(res1, -1000, 3000, 0, 1024); // res2 = map(res2, 0, 10000, 0, 1024); // res3 = map(res3, 0, 20000, 0, 1024); // res4 = map(res4, 15000, 60000, 0, 1024); // Serial.println(r); // the above lines can be uncommented if initial mapping of the copper plates needs to be done // for the plotter Serial.print(res1); Serial.print(" "); Serial.print(res2); Serial.print(" "); Serial.print(res3); Serial.print(" "); Serial.print(res4); Serial.print(" "); delay(100); // mapping the lights to different step response ranges // if (res1 > 1000 & res2<1000 & res3 < 1000 & res4 < 1000) // { // setNeos(255, 0, 0); // Serial.println("R"); // } // // if (res1<800 & res2 > 600 & res3 < 1000 & res4 < 1000) // { // setNeos(0, 255, 0); // Serial.println("G"); // } // // if (res1 < 800 & res2<600 & res3 <600 & res4 < 800) // { // setNeos(0, 0, 255); // Serial.println("B"); // } // // if (res1 < 1000 & res2<600 & res3 < 800 & res4 <100) // { // setNeos(128, 255, 128); // Serial.println("RGB"); // } // since the ranges kept fluctuating, the findMin() function to find the lowest absolute value to use as trigger int m = findMin(res1, res2, res3, res4); if (m == 1) { // setNeos(255, 0, 0); setBodhiTree(); Serial.println("R"); } if (m == 2) { // setNeos(0, 255, 0); setKalpavriksha(); Serial.println("G"); } if (m == 3) { setEden(); // setNeos(0, 0, 255); Serial.println("B"); } if (m == 4) { // setNeos(128, 255, 128); setYgg(); Serial.println("RGB"); } } void setNeos(int r, int g, int b) //old code kept here since I used it for initial testing before changing to the story based light colour schemes { for (int i = 0; i < NUMPIXELS; i++) { // For each pixel... // pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255 // Here we're using a moderately bright green color: // int r = random(0, 128); // int g = random(0, 128); // int b = random(0, 128); pixels.setPixelColor(i, pixels.Color(r, g, b)); pixels.show(); // Send the updated pixel colors to the hardware. delay(DELAYVAL); // Pause before next pass through loop } } int findMin( int a, int b, int c, int d) // to find the minimum of 4 values. // I am sure there are built in functions to do this but I was in a hurry and writing one out was faster { int min = 90000; if (a < min) { min = a; Serial.print("a "); Serial.print(min); Serial.print(" "); } if (b < min) { min = b; Serial.print("b "); Serial.print(min); Serial.print(" "); } if (c < min) { min = c; Serial.print("c "); Serial.print(min); Serial.print(" "); } if (d < min) { min = d; Serial.print("d "); Serial.print(min); Serial.print(" "); } int final; final = 0; if (min == a) { final = 1; } if (min == b) { final = 2; } if (min == c) { final = 3; } if (min == d) { final = 4; } Serial.println(final); return final; //lots of print and println for debugging, can be cleaned up and commented out later once not needed } void setBodhiTree() //story 1 - The buddha under the bodhi tree { pixels.setPixelColor(0, pixels.Color(255, 128, 0)); //Orange Buddha for (int i = 1; i < NUMPIXELS; i++) { int r = random(128); int b = random(128); pixels.setPixelColor(i, pixels.Color(r, 255, b)); //shades of green pixels.show(); delay(DELAYVAL); } } void setEden() //story 2 - the serpent and the apple in eden { pixels.setPixelColor(0, pixels.Color(0, 255, 0)); //serpent green for (int i = 1; i < NUMPIXELS; i++) { int r = random(255); int b = random(128); pixels.setPixelColor(i, pixels.Color(r, 255, b)); //leaves of lighter green float k = random(10); if (k > 8) //20% probability { pixels.setPixelColor(i, pixels.Color(255, 64, 64)); //pink-red fruit } pixels.show(); delay(DELAYVAL); } } void setYgg() //story 3 - Odin hanging from Yggdrasil { pixels.setPixelColor(0, pixels.Color(255, 255, 255)); //base white pixels.setPixelColor(1, pixels.Color(0, 0, 255)); //Odin blue // pixels.setPixelColor(1, pixels.Color(255, 128, 128)); for (int i = 2; i < NUMPIXELS; i++) { int r = random(128); int b = random(128); pixels.setPixelColor(i, pixels.Color(r, 255, b)); //shades of green float k = random(10); if (k > 8) { r = random(255); pixels.setPixelColor(i, pixels.Color(r, 255, b)); //some yellow, 20% proability } pixels.show(); delay(DELAYVAL); } } void setKalpavriksha() //story 4 - The wish granting tree { for (int i = NUMPIXELS; i > 0; i--) { int r = random(0, 200); //not 255 to prevent high brightness LEDs here so some can become fruits/flowers below int g = random(0, 200); //and also prevent current overload in case of many LEDs at high level brightness int b = random(0, 200); pixels.setPixelColor(i, pixels.Color(r, g, b)); float k = random(10); if (k > 8) { r = random(255); g = random(255); b = random(255); pixels.setPixelColor(i, pixels.Color(r, g, b)); //20% probability of full-brightness level } pixels.show(); delay(DELAYVAL); } }