// // wirelessly connected cloud or crowd // over WIFI over Internet over Mountains // across Rivers and the Universe // // // tailored for "Saekki-Chigi4" // 2026 04 13 - Seoul // // // NOTES // // ** IDENTITY ** #define MY_SPECIES ("CHIME") #define MY_NAME ("CHIMEE {a.k.a. chime1}") //arduino #include //wifi manager #include //osc over UDP #include #include #include #include #include // WiFiUDP Udp; // const IPAddress outIp(192,168,199,179); // server ip const unsigned int outPort = 9999; // server port const unsigned int localPort = 8888; // my port opened (<== expecting connection) OSCErrorCode error; //task #include Scheduler runner; //-*-*-*-*-*-*-*-*-*-*-*-*- // servo #define MOTOR_1A (D6) #define MOTOR_1B (D5) int speed = 0; bool isactive = false; void set_speed() { int r = speed; // if (r >= 0) { digitalWrite(MOTOR_1A, LOW); analogWrite(MOTOR_1B, r); } else { digitalWrite(MOTOR_1B, LOW); analogWrite(MOTOR_1A, r*(-1)); } // Serial.print("set_speed:"); // Serial.println(r); isactive = true; } Task set_speed_task(0, TASK_ONCE, &set_speed, &runner, false); // void rest() { analogWrite(MOTOR_1A, LOW); analogWrite(MOTOR_1B, LOW); isactive = false; } Task rest_task(0, TASK_ONCE, &rest, &runner, false); // #define MOTOR_2A (D3) #define MOTOR_2B (D2) int speed2 = 0; void set_speed2() { int r = speed2; // if (r >= 0) { digitalWrite(MOTOR_2A, LOW); analogWrite(MOTOR_2B, r); } else { digitalWrite(MOTOR_2B, LOW); analogWrite(MOTOR_2A, r*(-1)); } // Serial.print("set_speed2:"); // Serial.println(r); } Task set_speed2_task(0, TASK_ONCE, &set_speed2, &runner, false); // void rest2() { analogWrite(MOTOR_2A, LOW); analogWrite(MOTOR_2B, LOW); } Task rest2_task(0, TASK_ONCE, &rest2, &runner, false); //*-*-*-*-*-*-*-*-*-*-*-*-* //*-*-*-*-*-*-*-*-*-*-*-*-* //expressions //riff_A std::vector< std::vector > chimeA = { {0.4,0.133332,-0.409527,0.142857,-0.46667,0.619048,0.104762,-0.495242,-0.361908,0.466668}, //10 {0.809524,0.809524,0.819048,0.819048,0.819048,0.809524,0.7,0.695239,0.695239,0.695239,0.695239,0.438095,0.695239,0.690477,0.685715,0.447619,0.680952,0.680952,0.680952,0.680952,0.680952,0.82381,0.82381,0.666666,0.666666,0.671429,0.671429,0.814286,0.814286,0.657142,0.657142,0.657142,0.642856,0.623807,0.623807,0.623807,0.809524,0.361905,0.809524,0.361905,0.714285,0.714285,0.723809,0.761905,0.761905,0.771429,0.771429,0.771429,0.771429,0.800001} //50 }; // extern Task riff_A_task; int wordA = 0; float rateA = 900.0; // * 900 (scaling factor) float intervalA = 2000.0; //2000 ms void riff_A() { //check out next letter! (==value) speed = chimeA[wordA][riff_A_task.getRunCounter()-1] * rateA; set_speed_task.restart(); //info Serial.print("riff_A (i="); Serial.print(riff_A_task.getRunCounter()-1); Serial.print(", r="); Serial.print(speed); Serial.println(")"); //if we are done... schedule a 'rest_task' if (riff_A_task.isLastIteration()) { rest_task.restartDelayed(intervalA + 100); } } Task riff_A_task(0, TASK_ONCE, &riff_A, &runner, false); // void riff_A_start() { riff_A_task.setInterval(intervalA); riff_A_task.setIterations(chimeA[wordA].size()); riff_A_task.restart(); // Serial.print("riff_A_start with wordA #"); Serial.println(wordA); } Task riff_A_start_task(0, TASK_ONCE, &riff_A_start, &runner, false); // //riff_B std::vector< std::vector > chimeB = { {0.4,0.133332,-0.409527,0.142857,-0.46667,0.619048,0.104762,-0.495242,-0.361908,0.466668}, //10 {0.809524,0.809524,0.819048,0.819048,0.819048,0.809524,0.7,0.695239,0.695239,0.695239,0.695239,0.438095,0.695239,0.690477,0.685715,0.447619,0.680952,0.680952,0.680952,0.680952,0.680952,0.82381,0.82381,0.666666,0.666666,0.671429,0.671429,0.814286,0.814286,0.657142,0.657142,0.657142,0.642856,0.623807,0.623807,0.623807,0.809524,0.361905,0.809524,0.361905,0.714285,0.714285,0.723809,0.761905,0.761905,0.771429,0.771429,0.771429,0.771429,0.800001} //50 }; // extern Task riff_B_task; int wordB = 0; float rateB = 900.0; // * 900 (scaling factor) float intervalB = 2000.0; //2000 ms void riff_B() { //check out next letter! speed2 = chimeB[wordB][riff_B_task.getRunCounter()-1] * rateB; set_speed2_task.restart(); //info Serial.print("riff_B (i="); Serial.print(riff_B_task.getRunCounter()-1); Serial.print(", r="); Serial.print(speed2); Serial.println(")"); //if we are done... schedule a 'rest_task' if (riff_B_task.isLastIteration()) { rest2_task.restartDelayed(intervalB + 100); } } Task riff_B_task(0, TASK_ONCE, &riff_B, &runner, false); // void riff_B_start() { riff_B_task.setInterval(intervalB); riff_B_task.setIterations(chimeB[wordB].size()); riff_B_task.restart(); // Serial.print("riff_B_start with wordB #"); Serial.println(wordB); } Task riff_B_start_task(0, TASK_ONCE, &riff_B_start, &runner, false); //*-*-*-*-*-*-*-*-*-*-*-*-* //*-*-*-*-*-*-*-*-*-*-*-*-* // conductor for today (temporary conductor until wifi enabled.) // extern Task conductor_lonely_task; float lonelytime = 5000; //ms void conductor_lonely() { // static int count = 0; if (count == chimeA.size()) count = 0; // if (isactive == false) { // if no more movement, then start another lonely song. // isactive = true; // lonelytime = random(3, 10) * 10000.0; //ms // wordA = count; riff_A_start_task.restartDelayed(lonelytime); wordB = count; riff_B_start_task.restartDelayed(lonelytime); // Serial.print("conductor_lonely with lonelytime => "); Serial.println(lonelytime); Serial.print("conductor_lonely with count #"); Serial.println(count); // count++; } } Task conductor_lonely_task(1000, TASK_FOREVER, &conductor_lonely, &runner, false); //*-*-*-*-*-*-*-*-*-*-*-*-* // ==[DISABLE]== // //task #0 : blink led // #define LED_PERIOD (11111) // #define LED_ONTIME (1) // #define LED_GAPTIME (222) // #define LED_PIN 2 // extern Task blink_task; // void blink() { // // // static int count = 0; // count++; // // // switch (count % 4) { // case 0: // digitalWrite(LED_PIN, LOW); // first ON // blink_task.delay(LED_ONTIME); // break; // case 1: // digitalWrite(LED_PIN, HIGH); // first OFF // blink_task.delay(LED_GAPTIME); // break; // case 2: // digitalWrite(LED_PIN, LOW); // second ON // blink_task.delay(LED_ONTIME); // break; // case 3: // digitalWrite(LED_PIN, HIGH); // second OFF // blink_task.delay(LED_PERIOD - 2* LED_ONTIME - LED_GAPTIME); // break; // } // } // Task blink_task(0, TASK_FOREVER, &blink, &runner, true); // -> ENABLED, at start-up. //task #1 : osc processing void route_note(OSCMessage& msg, int offset) { if (msg.fullMatch("/word", offset)) { wordA = msg.getFloat(0); wordB = msg.getFloat(0); riff_A_start_task.restartDelayed(100); riff_B_start_task.restartDelayed(100); // Serial.print("OSC: /word : "); Serial.print(wordA); Serial.print(", "); Serial.println(wordB); } } extern Task osc_task; void osc() { //osc OSCMessage msg; int size = Udp.parsePacket(); if (size > 0) { while (size--) { msg.fill(Udp.read()); } if(!msg.hasError()) { // on '/yellow' msg.route("/yellow", route_note); Serial.println("OSC: /yellow"); } } } Task osc_task(0, TASK_FOREVER, &osc, &runner, true); // -> ENABLED, at start-up. // void setup() { //led // pinMode(LED_PIN, OUTPUT); //pwm freq. analogWriteFreq(40000); //serial Serial.begin(115200); delay(100); //info Serial.println(); Serial.println(); Serial.println("\"hi, i m your friend.\""); Serial.println("-"); Serial.println("- my species: \"" + String(MY_SPECIES) + "\""); Serial.println("- call me ==> \"" + String(MY_NAME) + "\""); Serial.println("- mac address: " + WiFi.macAddress()); Serial.println("-"); // //wifi-manager // Serial.println("- calling.. wifimanager"); // WiFiManager wm; // if (!wm.autoConnect()) ESP.restart(); // Serial.println("- i m connected!"); //open up udp connection Serial.println("- IP address: "); Serial.println(WiFi.localIP()); Serial.println("- Starting UDP"); Udp.begin(localPort); Serial.print("- Local port: "); Serial.println(Udp.localPort()); //all done. Serial.println("-"); Serial.println("\".-.-.-. :)\""); Serial.println(); //random seed randomSeed(analogRead(0)); //tasks rest_task.restartDelayed(500); rest2_task.restartDelayed(500); wordA = 0; riff_A_start_task.restartDelayed(1000); wordB = 0; riff_B_start_task.restartDelayed(1000); conductor_lonely_task.restartDelayed(5000); // // for (int idx = 0; idx < chimeA.size(); idx++) Serial.println(chimeA[idx].size()); // for (int idx = 0; idx < chimeB.size(); idx++) Serial.println(chimeB[idx].size()); // } void loop() { // runner.execute(); // }