381 lines
13 KiB
C++
381 lines
13 KiB
C++
//
|
|
// wirelessly connected cloud or crowd
|
|
// over WIFI over Internet over Mountains
|
|
// across Rivers and into the Universe
|
|
//
|
|
|
|
//
|
|
// tailored for "Saekki-Chigi4"
|
|
// 2026 04 13 - Seoul
|
|
//
|
|
|
|
//
|
|
// NOTES
|
|
//
|
|
// taskscheduler 기반으로 cnmat/osc/udp 로 esp8266에서 led를 on/off 하는 sub장치를 만드는데.. taskscheduler는 우선 필요없지만.. .. ? 그렇네.. + wifimanager를 넣어주고.. arduinoota도 기본으로 넣어주고.. taskscheduler는.. 그러니까... 모터 움직임 패턴을 읽어서.. 그대로 모터를 한번 돌려주는 걸로하고... 읽는 시간 rate 일정한 값 + 패턴 값 저장하는 어레이 2개.. 모터 2개 드라이브. roller2..
|
|
//
|
|
// 1 taskschduler + array + roller2 기반.. reset되면 몇 초 후에.. 패턴 1을 재생하도록. -> DONE
|
|
// 2 여기에 osc_udp 추가해서.. 외부에서, 패턴을 실행시킬 수 있도록. (pd로 osc로 전송) -> DONE
|
|
// 3 여기에 wifimanager를 더해서.. 외부에서, 와이파이 설정도 하고, 상태 업데이트 할 수 있도록. (근데 이걸 위해서, 특수한 버튼 눌러야 한다면 flash버튼을 이용해 보던가.)
|
|
// 4 이 모듈이 접속할 웹 공간 준비. 도메인 + 서비스. 그곳에 world energy 패치 준비.. (pd 여도 좋음.) - 아니면, 웹페이지여도 좋음. / 여기서 WE가 취합되고, 평균되고, 발표됨. 각 모듈은 이 값을 읽어감. (여기까지가 기존의 셋업 -> 인터넷으로 옮겨간 상태임.)
|
|
//
|
|
// -- 우선은 여기까지 하면, 갈수 있을지도 --
|
|
//
|
|
// 5 pd에서 패턴값과.. 기본 파라미터를 조정하는 메세지 주기.. (+ 패턴값 체크하는 기능도 있으면 좋음...)
|
|
//
|
|
|
|
// ** IDENTITY **
|
|
#define MY_SPECIES ("YELLOW")
|
|
#define MY_NAME ("YELOWEE {a.k.a. yellow1}")
|
|
|
|
// ** WIFI **
|
|
char ssid[] = "TEEPOT";
|
|
char pass[] = "3333388888";
|
|
|
|
//arduino
|
|
#include <Arduino.h>
|
|
|
|
//osc over UDP
|
|
#include <ESP8266WiFi.h>
|
|
#include <WiFiUdp.h>
|
|
#include <OSCMessage.h>
|
|
#include <OSCBundle.h>
|
|
#include <OSCData.h>
|
|
//
|
|
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 <TaskScheduler.h>
|
|
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<float> > yellowA = {
|
|
{0.266667,0.285714,0.295238,0.32381,0.352381,0.371429,0.409525,0.2,0.228572,0.257143,0.276191,0.285715,0.314286,0.32381,0.352382,0.37143,0.390477,0.238095,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.171429,0.209524,0.257143,0.276191,0.304763,0.333334,0.342858,-0.00952393,-0.00952393,-0.00952393,-0.00952393,-0.00952393,-0.00952393,-0.00952393,-0.00952393,-0.00952393,-0.00952393,-0.00952393},
|
|
//50
|
|
|
|
{0.704762,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.733333,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.704762,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.695238,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.714286,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.0190475,0.704762,0.0190475},
|
|
//50
|
|
|
|
{-0.00952327,0.771429,-0.00952327,-0.00952327,-0.00952327,-0.00952327,-0.00952327,-0.00952327,-0.00952327,-0.00952327,-0.00952327,-0.00952327,-0.00952327,0.771429,-0.00952327,-0.00952327,-0.00952327,1.78814e-07,1.78814e-07,1.78814e-07,1.78814e-07,1.78814e-07,1.78814e-07,1.78814e-07,1.78814e-07,1.78814e-07,0.780952,1.78814e-07,1.78814e-07,1.78814e-07,1.78814e-07,0,0,0,0,0,0,0,0,0,0,0,0,0.8,0,0,0,0,0,0,0,0,0,0,0,0,0,0.8,0,0,0,0,0,0,0,0,0,0,0,0.809524,0,0,0,0,0,0,0,0,0,0},
|
|
//80
|
|
|
|
{0.790476,-0.00952387,-0.00952387,0,0,0,0,0.780952,0,0,0,0,0,0,0,0.771429,0,0,0,0,0,0,0,0,0.790476,0,0,0,0,0}
|
|
//30
|
|
};
|
|
//
|
|
extern Task riff_A_task;
|
|
int wordA = 0;
|
|
float rateA = 150.0; // * 100 (scaling factor)
|
|
// 94:b9:7e:?? ?? ?? => 100
|
|
// 94:b9:7e:14:4e:2c => 150 (?)
|
|
// 94:b9:7e:14:49:b6 => 20
|
|
float intervalA = 500.0; //500 ms
|
|
void riff_A() {
|
|
if (riff_A_task.isLastIteration()) {
|
|
//we are done. stop now.
|
|
rest_task.restart();
|
|
} else {
|
|
//check out next letter!
|
|
speed = yellowA[wordA][riff_A_task.getRunCounter()-1] * rateA;
|
|
set_speed_task.restart();
|
|
}
|
|
Serial.print("riff_A (i=");
|
|
Serial.print(riff_A_task.getRunCounter()-1);
|
|
Serial.print(", r=");
|
|
Serial.print(speed);
|
|
Serial.println(")");
|
|
}
|
|
Task riff_A_task(0, TASK_ONCE, &riff_A, &runner, false);
|
|
//
|
|
void riff_A_start() {
|
|
riff_A_task.setInterval(intervalA);
|
|
riff_A_task.setIterations(yellowA[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<float> > yellowB = {
|
|
{0.685715,0.723811,0.800002,0.485714,0.519047,0.552381,0.580953,0,0,0,0,0,0,0,0,0.533333,0.571429,0.604762,0.638096,0.653969,0.669842,0.685715,0.695239,4.17233e-07,0.00952381,0.00952381,0.00952381,0.00952381,0.00952381,0.00952381,0.00952381,0.366666,0.380951,0.399999,0.423809,0.933336,0.952384,0.957145,0.961907,0,0,0,0,0,0,0.438095,0.457142,0.457142,0,0.361904},
|
|
//50
|
|
|
|
{0,0.742857,0.00952387,0.00952387,0.00952387,0.00952387,0.742857,0.00952387,0.00952387,0.00952387,0.00952387,0.00952387,0.00952387,0.742857,0.00952387,0.00952387,0.00952387,0.00952387,0.00952387,0.00952387,0.742857,0.00952387,0.00952387,0.00952387,0.00952387,0.00952387,0.00952387,0.742857,0.00952387,0.00952387,0.00952387,0.742857,0.00952387,0.00952387,0.00952387,0.00952387,0.00952387,0.742857,0.00952387,0.00952387,0.00952387,0.00952387,0.714286,0.00952387,0.00952387,0.00952387,0.00952387,0.00952387,0.00952387,-5.96046e-08},
|
|
//50
|
|
|
|
{0,0.761905,0.685716,0.657145,0.504762,0.419048,0.390478,0,0,0,0,0,0,0,0,0,0.647619,0.8,0.609524,0.52381,0.428574,0,0,0,0,0,0,0,0,0,0.790476,0.685715,0.504764,0.476194,0.409528,0,0,0,0,0,0,0,0,0,0,0.8,0.647621,0.561909,0,0,0,0,0,0,0,0,0,0,0,0,0.847619,0.780953,0.704764,0.638098,0.552386,0.523815,0,0,0,0,0,0,0,0,0.866667,0.704763,0.619051,0.600003,0,0},
|
|
//80
|
|
|
|
{0.819048,0.819048,0.819048,-0.323816,-0.323816,0.819048,0.819048,0.819048,0.819048,0.828571,0.828571,0.828571,0.838095,-0.361912,-0.361912,0.847619,0.857143,0.857143,0.857143,0.857143,0.866666,0.866666,0.866666,-0.428579,-0.428579,0.866666,0.857143,0.847619,0.838095,0.809524}
|
|
//30
|
|
};
|
|
//
|
|
extern Task riff_B_task;
|
|
int wordB = 0;
|
|
float rateB = 150.0; // * 100 (scaling factor)
|
|
// 94:b9:7e:?? ?? ?? => 100
|
|
// 94:b9:7e:14:4e:2c => 150 (?)
|
|
// 94:b9:7e:14:49:b6 => 20
|
|
float intervalB = 500.0; //500 ms
|
|
void riff_B() {
|
|
if (riff_B_task.isLastIteration()) {
|
|
//we are done. stop now.
|
|
rest2_task.restart();
|
|
} else {
|
|
//check out next letter!
|
|
speed2 = yellowB[wordB][riff_B_task.getRunCounter()-1] * rateB;
|
|
set_speed2_task.restart();
|
|
}
|
|
Serial.print("riff_B (i=");
|
|
Serial.print(riff_B_task.getRunCounter()-1);
|
|
Serial.print(", r=");
|
|
Serial.print(speed2);
|
|
Serial.println(")");
|
|
}
|
|
Task riff_B_task(0, TASK_ONCE, &riff_B, &runner, false);
|
|
//
|
|
void riff_B_start() {
|
|
riff_B_task.setInterval(intervalB);
|
|
riff_B_task.setIterations(yellowB[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 == yellowA.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); //check every 10 sec.
|
|
//*-*-*-*-*-*-*-*-*-*-*-*-*
|
|
|
|
// ==[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
|
|
// system_phy_set_max_tpw(0);
|
|
// WiFiMode_t node_type = WIFI_STA;
|
|
// WiFi.mode(node_type);
|
|
|
|
// test wifi udp
|
|
WiFi.begin(ssid, pass);
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
delay(500);
|
|
Serial.print(".");
|
|
}
|
|
Serial.println("");
|
|
Serial.println("WiFi connected");
|
|
Serial.println("IP address: ");
|
|
Serial.println(WiFi.localIP());
|
|
Serial.println("Starting UDP");
|
|
Udp.begin(localPort);
|
|
Serial.print("Local port: ");
|
|
Serial.println(Udp.localPort());
|
|
|
|
//
|
|
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 < yellowA.size(); idx++) Serial.println(yellowA[idx].size());
|
|
// for (int idx = 0; idx < yellowB.size(); idx++) Serial.println(yellowB[idx].size());
|
|
//
|
|
}
|
|
|
|
void loop() {
|
|
//
|
|
runner.execute();
|
|
//
|
|
}
|