postman<->teensy comm. updated (I2C --> Serial)

This commit is contained in:
Dooho Yi 2021-02-15 21:09:20 +09:00
parent 615a6eeab9
commit 50bac35c13
7 changed files with 533 additions and 296 deletions

226
osc/main_taskscheduler.cpp Normal file
View file

@ -0,0 +1,226 @@
//
// wirelessly connected cloud (Wireless Mesh Networking)
//
//
// Conversations about the ROOT @ SEMA warehouses, Seoul
//
//
// 2021 02 15
//
// (part-2) teensy35 : 'client:osc' (osc over slip --> mesh post)
//
//arduino
#include <Arduino.h>
//osc (already included in "framework-arduinoteensy")
#include <OSCBundle.h>
#include <SLIPEncodedUSBSerial.h>
SLIPEncodedUSBSerial SLIPSerial(Serial);
//post definition
#include "../../post.h"
//postman's uart
#define POSTMAN_SERIAL (Serial3)
//
void midinote(OSCMessage& msg, int offset) {
// matches will happen in the order. that the bundle is packed.
static int pitch = 0;
static int velocity = 0;
static int onoff = 0;
static int x1 = 0;
static int x2 = 0;
static int x3 = 0;
static int x4 = 0;
static int ps = 0;
// (1) --> /onoff
if (msg.fullMatch("/onoff", offset)) {
//
pitch = 0;
velocity = 0;
onoff = 0;
//
onoff = msg.getInt(0);
if (onoff != 0) onoff = 1;
}
// (2) --> /velocity
if (msg.fullMatch("/velocity", offset)) {
velocity = msg.getInt(0);
if (velocity < 0) velocity = 0;
// if (velocity > 127) velocity = 127;
if (velocity > 999) velocity = 999;
}
// (3) --> /pitch
if (msg.fullMatch("/pitch", offset)) {
pitch = msg.getInt(0);
if (pitch < 0) pitch = 0;
// if (pitch > 127) pitch = 127;
if (pitch > 999) pitch = 999;
}
// (4) --> /x
if (msg.fullMatch("/x", offset)) {
x1 = msg.getInt(0);
x2 = msg.getInt(1);
x3 = msg.getInt(2);
x4 = msg.getInt(3);
ps = msg.getInt(4);
char letter[POST_BUFF_LEN] = "";
snprintf(letter, POST_BUFF_LEN, "[%03d%03d%01dX%05d%05d%05d%05d%02d]",
pitch,
velocity,
onoff,
x1,
x2,
x3,
x4,
ps);
POSTMAN_SERIAL.print(letter);
}
}
//task
#include <TaskScheduler.h>
Scheduler runner;
void osc_listen () {
//
static OSCBundle bundleIN;
int size = 0;
while (!SLIPSerial.endofPacket()) {
if ((size = SLIPSerial.available()) > 0) {
while(size--) {
bundleIN.fill(SLIPSerial.read());
}
}
}
//
if(!bundleIN.hasError()) {
bundleIN.route("/note", midinote);
//
bundleIN.empty();
}
}
Task osc_listen_task(0, TASK_FOREVER, osc_listen, &runner, true); // aInterval == 0 >>> immediately re-schedule ?
//
// OSCBundle bundleIN;
// int size;
//
// while(!SLIPSerial.endofPacket())
// if( (size =SLIPSerial.available()) > 0)
// {
// while(size--)
// bundleIN.fill(SLIPSerial.read());
// }
//
// if(!bundleIN.hasError())
// bundleIN.dispatch("/led", LEDcontrol);
//
void postman_talk () {
//
static bool insync = false;
if (insync == false) {
int size;
if ((size = POSTMAN_SERIAL.available()) > 0) {
char last = '.';
while(size--) {
// get the last byte
last = POSTMAN_SERIAL.read();
}
// expectable last of the messages
if (last == ']' || last == '}') {
insync = true;
}
}
} else if (insync == true) {
if (POSTMAN_SERIAL.available() > POST_LENGTH) {
char cstr[POST_BUFF_LEN] = "................................";
// fetch all the bytes
POSTMAN_SERIAL.readBytes(cstr, POST_LENGTH);
// protocol checks
char first = cstr[0];
char last = cstr[POST_LENGTH-1];
if (first != '[' && first != '{') {
insync = false;
return; //error!!
}
if (last != ']' && last != '}') {
insync = false;
return; //error!!
}
//// OK -> parse && compose & send OSC message!
String msg = String(cstr);
// hello frame ( '{' + 30 bytes + '}' )
// : {123456789012345678901234567890}
// hello frame
// : {123456789012345678901234567890}
// : {IIIA111111222222333333444444__}
// : III - ID_KEY
// .substring(1, 4);
// : 1 - data of 6 letters
// .substring(9, 14);
// : 2 - data of 6 letters
// .substring(14, 19);
// : 3 - data of 6 letters
// .substring(19, 24);
// : 4 - data of 6 letters
// .substring(24, 29);
// received a hello.
String str_id = msg.substring(1, 4);
int id = str_id.toInt();
//
OSCMessage hello("/hello");
hello.add(id);
//
String str_aa = msg.substring(4, 5);
//
if (str_aa == "A") {
//
String str_h1 = msg.substring(5, 11);
String str_h2 = msg.substring(11, 17);
String str_h3 = msg.substring(17, 23);
String str_h4 = msg.substring(23, 29);
//
hello.add(str_h1.toInt());
hello.add(str_h2.toInt());
hello.add(str_h3.toInt());
hello.add(str_h4.toInt());
}
//
SLIPSerial.beginPacket();
hello.send(SLIPSerial);
SLIPSerial.endPacket();
hello.empty();
}
}
}
Task postman_talk_task(0, TASK_FOREVER, postman_talk, &runner, true); // aInterval == 0 >>> immediately re-schedule ?
//
void setup() {
//osc
SLIPSerial.begin(57600);
//
POSTMAN_SERIAL.begin(115200);
}
//
void loop() {
runner.execute();
}

View file

@ -15,6 +15,8 @@ env_default = teensy36
lib_deps = lib_deps =
721@3.0.2 ; TaskScheduler 721@3.0.2 ; TaskScheduler
; osc -> (already included in "framework-arduinoteensy")
[env:teensy35] [env:teensy35]
platform = teensy@3.6.0 platform = teensy@3.6.0
board = teensy35 board = teensy35

View file

@ -1,129 +1,41 @@
// //
// wirelessly connected cloud (Wireless Mesh Networking) // wirelessly connected cloud (Wireless Mesh Networking)
// MIDI-like
// spacial
// sampler keyboard
// //
// //
// Forest all/around @ MMCA, Seoul // Conversations about the ROOT @ SEMA warehouses, Seoul
// //
// //
// 2019 12 11 // 2021 02 15
// //
// (part-2) teensy35 : 'client:osc' (osc over slip --> mesh post) // (part-2) teensy35 : 'client:osc' (osc over slip --> mesh post)
// //
// especially, MIDI-like.
// collect following OSC msg.
//
// "/note/onoff"
// "/note/velocity"
// "/note/key"
//
// and build a MIDI-like letter post.
// and give it to the postman
//
//
// --[post]--> "sampler"
//
// letter frame ( '[' + 30 bytes + ']' )
// : [123456789012345678901234567890]
// 'MIDI' letter frame
// : [123456789012345678901234567890]
// : [KKKVVVG.......................]
// : KKK - Key
// .substring(1, 4);
// : VVV - Velocity (volume/amp.)
// .substring(4, 7);
// : G - Gate (note on/off)
// .substring(7, 8);
//
//
// 2021 01 10
//
// : [_______X......................]
// : X - Extension starter 'X'
// .substring(8, 9);
// "/note/x1" (4 digit)
// "/note/x2" (4 digit)
// "/note/x3" (3 digit)
// "/note/x4" (3 digit)
// "/note/x5" (2 digit)
// "/note/x6" (2 digit)
// "/note/x7" (2 digit)
// "/note/x8" (2 digit)
// Extension (X == 'X')
// : [_______X1111222233344455667788]
// : 1 - data of 4 letters
// .substring(9, 13);
// : 2 - data of 4 letters
// .substring(13, 17);
// : 3 - data of 3 letters
// .substring(17, 20);
// : 4 - data of 3 letters
// .substring(20, 23);
// : 5 - data of 2 letters
// .substring(23, 25);
// : 6 - data of 2 letters
// .substring(25, 27);
// : 7 - data of 2 letters
// .substring(27, 29);
// : 8 - data of 2 letters
// .substring(29, 31);
//arduino //arduino
#include <Arduino.h> #include <Arduino.h>
//osc //osc (already included in "framework-arduinoteensy")
#include <OSCBundle.h> #include <OSCBundle.h>
#include <SLIPEncodedUSBSerial.h> #include <SLIPEncodedUSBSerial.h>
SLIPEncodedUSBSerial SLIPSerial(Serial); SLIPEncodedUSBSerial SLIPSerial(Serial);
//i2c //post definition
#include <Wire.h> #include "../../post.h"
//postman's uart
#define POSTMAN_SERIAL (Serial3)
// --[post]--> "sampler" // --[post]--> "sampler"
#include "../../sampler/post_sampler.h" #include "../../post.h"
void receiveEvent(int howMany) {
// nothing to expect.. but.. let's just print out..
// while (Wire.available())
// Serial.print(Wire.read());
// Serial.println();
}
// well. i don't know how fast should i be able to send msg.. to the net..
// first test, and then.. if needed. will come back.
bool new_letter = false;
char letter_outro[POST_BUFF_LEN] = "................................";
void letter_outro_clear() {
// clear the letter buff
letter_outro[0] = '[';
for (int i = 1; i < POST_LENGTH-1; i++) letter_outro[i] = '.';
letter_outro[POST_LENGTH-1] = ']';
}
void requestEvent() {
if (new_letter) {
Wire.write(letter_outro, POST_LENGTH);
new_letter = false;
} else {
Wire.write(" "); // no letter to send
}
}
void I2CPrint(const String & str); // for DEBUG w/ I2C
// //
void setup() { void setup() {
//i2c
Wire.begin(I2C_ADDR);
Wire.onRequest(requestEvent);
Wire.onReceive(receiveEvent);
//osc //osc
SLIPSerial.begin(57600); SLIPSerial.begin(57600);
//
POSTMAN_SERIAL.begin(115200);
} }
// //
@ -136,10 +48,7 @@ void midinote(OSCMessage& msg, int offset) {
static int x2 = 0; static int x2 = 0;
static int x3 = 0; static int x3 = 0;
static int x4 = 0; static int x4 = 0;
static int x5 = 0; static int ps = 0;
static int x6 = 0;
static int x7 = 0;
static int x8 = 0;
// (1) --> /onoff // (1) --> /onoff
if (msg.fullMatch("/onoff", offset)) { if (msg.fullMatch("/onoff", offset)) {
// //
@ -154,14 +63,12 @@ void midinote(OSCMessage& msg, int offset) {
if (msg.fullMatch("/velocity", offset)) { if (msg.fullMatch("/velocity", offset)) {
velocity = msg.getInt(0); velocity = msg.getInt(0);
if (velocity < 0) velocity = 0; if (velocity < 0) velocity = 0;
// if (velocity > 127) velocity = 127;
if (velocity > 999) velocity = 999; if (velocity > 999) velocity = 999;
} }
// (3) --> /pitch // (3) --> /pitch
if (msg.fullMatch("/pitch", offset)) { if (msg.fullMatch("/pitch", offset)) {
pitch = msg.getInt(0); pitch = msg.getInt(0);
if (pitch < 0) pitch = 0; if (pitch < 0) pitch = 0;
// if (pitch > 127) pitch = 127;
if (pitch > 999) pitch = 999; if (pitch > 999) pitch = 999;
} }
// (4) --> /x // (4) --> /x
@ -170,13 +77,10 @@ void midinote(OSCMessage& msg, int offset) {
x2 = msg.getInt(1); x2 = msg.getInt(1);
x3 = msg.getInt(2); x3 = msg.getInt(2);
x4 = msg.getInt(3); x4 = msg.getInt(3);
x5 = msg.getInt(4); ps = msg.getInt(4);
x6 = msg.getInt(5);
x7 = msg.getInt(6);
x8 = msg.getInt(7);
// while (new_letter != false) {}; // <-- sort of semaphore.. but it doesn't work yet.. buggy. char letter[POST_BUFF_LEN] = "";
sprintf(letter_outro, "[%03d%03d%01dX%04d%04d%03d%03d%02d%02d%02d%02d]", snprintf(letter, POST_BUFF_LEN, "[%03d%03d%01dX%05d%05d%05d%05d%02d]",
pitch, pitch,
velocity, velocity,
onoff, onoff,
@ -184,20 +88,18 @@ void midinote(OSCMessage& msg, int offset) {
x2, x2,
x3, x3,
x4, x4,
x5, ps);
x6, POSTMAN_SERIAL.print(letter);
x7,
x8);
new_letter = true;
} }
} }
// //
void loop() { void loop() {
static String str = "";
//osc //osc
OSCBundle bundleIN; OSCBundle bundleIN;
int size; int size;
if (SLIPSerial.available()) {
while(!SLIPSerial.endofPacket()) { while(!SLIPSerial.endofPacket()) {
if( (size = SLIPSerial.available()) > 0) { if( (size = SLIPSerial.available()) > 0) {
while(size--) { while(size--) {
@ -208,28 +110,85 @@ void loop() {
if(!bundleIN.hasError()) { if(!bundleIN.hasError()) {
bundleIN.route("/note", midinote); bundleIN.route("/note", midinote);
} }
// else { }
// str = "error! : " + String(bundleIN.getError());
// I2CPrint(str);
// }
}
//==========<I2CPrint>========== //postman (serial comm.)
// utility func. -> for DEBUG w/ I2C static bool insync = false;
char buff[POST_LENGTH] = ""; if (insync == false) {
void I2CPrint(const String & str) { while (POSTMAN_SERIAL.available() > 0) {
const char * buff = str.c_str(); // check the last byte
int len = str.length(); char last = POSTMAN_SERIAL.read();
// while (new_letter != false) {}; // expectable last of the messages
letter_outro[0] = '['; if (last == ']' || last == '}') {
if (len > (POST_LENGTH - 2)) len = (POST_LENGTH - 2); insync = true;
for (int i = 0; i < len; i++) {
letter_outro[i+1] = buff[i];
} }
for (int j = len; j < (POST_LENGTH - 2); j++) {
letter_outro[j+1] = '_';
} }
letter_outro[POST_LENGTH-1] = ']'; }
new_letter = true; if (POSTMAN_SERIAL.available() > POST_LENGTH) {
char cstr[POST_BUFF_LEN] = "................................";
// fetch all the bytes
POSTMAN_SERIAL.readBytes(cstr, POST_LENGTH);
// protocol checks
char first = cstr[0];
char last = cstr[POST_LENGTH-1];
if (first != '[' && first != '{') {
insync = false;
}
if (last != ']' && last != '}') {
insync = false;
}
//// OK -> parse && compose & send OSC message!
String msg = String(cstr);
// hello frame ( '{' + 30 bytes + '}' )
// : {123456789012345678901234567890}
// hello frame
// : {123456789012345678901234567890}
// : {IIIA111111222222333333444444__}
// : III - ID_KEY
// .substring(1, 4);
// : 1 - data of 6 letters
// .substring(9, 14);
// : 2 - data of 6 letters
// .substring(14, 19);
// : 3 - data of 6 letters
// .substring(19, 24);
// : 4 - data of 6 letters
// .substring(24, 29);
// received a hello.
String str_id = msg.substring(1, 4);
int id = str_id.toInt();
//
OSCMessage hello("/hello");
hello.add(id);
//
String str_aa = msg.substring(4, 5);
//
if (str_aa == "A") {
//
String str_h1 = msg.substring(5, 11);
String str_h2 = msg.substring(11, 17);
String str_h3 = msg.substring(17, 23);
String str_h4 = msg.substring(23, 29);
//
hello.add(str_h1.toInt());
hello.add(str_h2.toInt());
hello.add(str_h3.toInt());
hello.add(str_h4.toInt());
}
//
SLIPSerial.beginPacket();
hello.send(SLIPSerial);
SLIPSerial.endPacket();
hello.empty();
}
} }
//==========</I2CPrint>=========

View file

@ -52,7 +52,7 @@
//============</list of reserved keys>=========== //============</list of reserved keys>===========
//============<identity key>============ //============<identity key>============
#define ID_KEY ROUNDLY_E_KEY #define ID_KEY ROUNDLY_I_KEY
//============</identity key>=========== //============</identity key>===========
//============<parameters>============ //============<parameters>============
@ -229,12 +229,45 @@ void rest() {
} }
Task rest_task(1000, TASK_FOREVER, &rest); Task rest_task(1000, TASK_FOREVER, &rest);
//sendhello - with 4 int // up to 6 letters for each
void sendhello (int hey0 = 0, int hey1 = 0, int hey2 = 0, int hey3 = 0) {
char msg_cstr[32+1] = "{/././././././././././././././.}";
snprintf(msg_cstr, 32+1, "{%03dA%06d%06d%06d%06d__}", ID_KEY, hey0, hey1, hey2, hey3);
mesh.sendBroadcast(String(msg_cstr));
}
//
String letter_ps = "00";
//
extern Task hello_task;
void hello() {
//
sendhello(
stepper.currentPosition(),
stepper.distanceToGo(),
stepper.distanceToGo(),
stepper.distanceToGo()
);
//
int ps_int = letter_ps.toInt();
if (ps_int > 0) {
hello_task.restartDelayed(ps_int * 100);
}
}
Task hello_task(0, TASK_ONCE, &hello);
// mesh callbacks // mesh callbacks
void receivedCallback(uint32_t from, String & msg) { // REQUIRED void receivedCallback(uint32_t from, String & msg) { // REQUIRED
Serial.print("got msg.: "); Serial.print("got msg.: ");
Serial.println(msg); Serial.println(msg);
//parse now. //parse now.
String str_type = msg.substring(0, 1);
// [letter...] >>> START
if (str_type == "[") {
//parse letter string. //parse letter string.
// letter frame ( '[' + 30 bytes + ']' ) // letter frame ( '[' + 30 bytes + ']' )
@ -258,37 +291,36 @@ void receivedCallback(uint32_t from, String & msg) { // REQUIRED
int velocity = str_velocity.toInt(); // 0 ~ 127 int velocity = str_velocity.toInt(); // 0 ~ 127
int gate = str_gate.toInt(); int gate = str_gate.toInt();
//is it for me?
if (key == ID_KEY) {
// : [_______X......................] // : [_______X......................]
// : X - Extension starter 'X' // : X - Extension starter 'X'
// .substring(8, 9); // .substring(8, 9);
// Extension (X == 'X') // Extension (X == 'X')
// : [_______X1111222233344455667788] // : [_______X11111222223333344444PS]
// : 1 - data of 4 letters // : 1 - data of 5 letters
// .substring(9, 13); // .substring(9, 14);
// : 2 - data of 4 letters // : 2 - data of 5 letters
// .substring(13, 17); // .substring(14, 19);
// : 3 - data of 3 letters // : 3 - data of 5 letters
// .substring(17, 20); // .substring(19, 24);
// : 4 - data of 3 letters // : 4 - data of 5 letters
// .substring(20, 23); // .substring(24, 29);
// : 5 - data of 2 letters // : PS - 2 letter
// .substring(23, 25);
// : 6 - data of 2 letters
// .substring(25, 27);
// : 7 - data of 2 letters
// .substring(27, 29);
// : 8 - data of 2 letters
// .substring(29, 31); // .substring(29, 31);
String str_ext = msg.substring(8, 9); String str_ext = msg.substring(8, 9);
String str_x1 = msg.substring(9, 13); //
String str_x2 = msg.substring(13, 17); String str_x1 = msg.substring(9, 14);
String str_x3 = msg.substring(17, 20); String str_x2 = msg.substring(14, 19);
String str_x4 = msg.substring(20, 23); String str_x3 = msg.substring(19, 24);
String str_x5 = msg.substring(23, 25); String str_x4 = msg.substring(24, 29);
String str_x6 = msg.substring(25, 27); // p. s.
String str_x7 = msg.substring(27, 29); letter_ps = msg.substring(29, 31);
String str_x8 = msg.substring(29, 31); if (letter_ps.toInt() > 0) {
hello_task.restartDelayed(10);
}
if (str_ext == "X") { if (str_ext == "X") {
int step_target_multiplier = str_x3.toInt(); // -99 ~ 999 int step_target_multiplier = str_x3.toInt(); // -99 ~ 999
@ -296,14 +328,61 @@ void receivedCallback(uint32_t from, String & msg) { // REQUIRED
step_duration = str_x2.toInt(); // -999 ~ 9999 step_duration = str_x2.toInt(); // -999 ~ 9999
} }
//is it for me? //
if (key == ID_KEY) {
if (gate == 1) { if (gate == 1) {
stepping_task.restartDelayed(10); stepping_task.restartDelayed(10);
} else if (gate == 0) { } else if (gate == 0) {
rest_task.restartDelayed(10); rest_task.restartDelayed(10);
} }
} }
}
//END <<< [letter...]
//{hello...} >>> START
else if (str_type == "{") {
// hello frame ( '{' + 30 bytes + '}' )
// : {123456789012345678901234567890}
// hello frame
// : {123456789012345678901234567890}
// : {IIIA111111222222333333444444__}
// : III - ID_KEY
// .substring(1, 4);
// : 1 - data of 6 letters
// .substring(9, 14);
// : 2 - data of 6 letters
// .substring(14, 19);
// : 3 - data of 6 letters
// .substring(19, 24);
// : 4 - data of 6 letters
// .substring(24, 29);
// received a hello.
String str_id = msg.substring(1, 4);
int id = str_id.toInt();
//is it for me?
if (id == ID_KEY) {
//
String str_aa = msg.substring(4, 5);
//
String str_h1 = msg.substring(5, 11);
String str_h2 = msg.substring(11, 17);
String str_h3 = msg.substring(17, 23);
String str_h4 = msg.substring(23, 29);
//
if (str_aa == "A") {
}
}
}
//END <<< {hello...}
} }
void changedConnectionCallback() { void changedConnectionCallback() {
Serial.println(mesh.getNodeList().size()); Serial.println(mesh.getNodeList().size());
@ -437,6 +516,7 @@ void setup() {
//tasks //tasks
runner.addTask(stepping_task); runner.addTask(stepping_task);
runner.addTask(rest_task); runner.addTask(rest_task);
runner.addTask(hello_task);
rest_task.restartDelayed(500); rest_task.restartDelayed(500);
} }

View file

@ -1,17 +0,0 @@
#pragma once
#include "../post.h"
//
// letter frame ( '[' + 30 bytes + ']' )
// : [123456789012345678901234567890]
// 'MIDI' letter frame
// : [123456789012345678901234567890]
// : [KKKVVVG.......................]
// : KKK - Key
// .substring(1, 4);
// : VVV - Velocity (volume/amp.)
// .substring(4, 7);
// : G - Gate (note on/off)
// .substring(7, 8);
//

View file

@ -144,7 +144,7 @@ Task sample_player_check_task(0, TASK_FOREVER, sample_player_check, &runner, tru
//i2c //i2c
#include <Wire.h> #include <Wire.h>
#include "../post_sampler.h" #include "../../post.h"
// DISABLED.. due to bi-directional I2C hardship. ==> use UART. // DISABLED.. due to bi-directional I2C hardship. ==> use UART.
// void requestEvent() { // void requestEvent() {
// Wire.write(" "); // no letter to send // Wire.write(" "); // no letter to send

View file

@ -1,16 +1,13 @@
// //
// wirelessly connected cloud (Wireless Mesh Networking) // wirelessly connected cloud (Wireless Mesh Networking)
// MIDI-like
// spacial
// sampler keyboard
// //
// //
// Forest all/around @ MMCA, Seoul // Conversation about the ROOT @ SEMA warehouses, Seoul
// //
// //
// 2019 12 10 // 2021 02 15
// //
// (part-1) esp8266 : 'postman' (the mesh network nodes) // (part-1) esp8266 : 'postman' (the mesh network nodes)
// //
@ -26,15 +23,14 @@
// we can broadcast/unicast/recv. msg. w/ meshID and nodelist // we can broadcast/unicast/recv. msg. w/ meshID and nodelist
// so, let's just use it. // so, let's just use it.
// //
// but one specific thing is that we will use I2C comm. to feed this postman. // but one specific thing is that we had used I2C comm. to feed this postman.
// and I2C is a FIXED-length msg. // and I2C was a FIXED-length msg.
// so, at least, we need to fix this length of the msg.
// otherwise, we need to do variable-length comm. like uart. to feed/fetch msg. from postman.
// //
// well, okay. but, let's just do.. I2C. and fix a length. // but we will use UART instead of I2C, because I2C was not feasible for true bi-directional comm. between teensy <-> esp8266
// maybe, ... 32 bytes? // that's a thing of board-specific. in general it should be ok. but this particular case, it was hard to solve.
// so, then, this postman will read/write I2C channel. always.. 32 bytes. //
// and then, this 32 bytes will be flying in the clouds. // yet, we were very satisfied with previous 'fixed length (32 bytes)' comm.
// so even though we are free to use variable-length messages, since using UART comm., we want to stick to that 'fixed-length' frame defs.
// //
//==========<configurations>=========== //==========<configurations>===========
@ -46,12 +42,8 @@
// we need who can do AP.. // we need who can do AP..
// ==> TODO! just prepare some 'dummy' postmans around. w/ AP activated. // ==> TODO! just prepare some 'dummy' postmans around. w/ AP activated.
// //
// 'DISABLE_I2C_REQ' // 'DISABLE_I2C_REQ' (DEPRECATED)
// --> a quirk.. due to bi-directional I2C hardship. // --> DEPRECATED: we are not using I2C anymore.
// ideally, we want to make this sampler node also speak.
// but, I2C doesn't work. maybe middleware bug.. we later want to change to diff. proto.
// for example, UART or so.
// ==> BEWARE! yet, still we need to take off this.. for 'osc' node.
// //
// 'SET_ROOT' // 'SET_ROOT'
// 'SET_CONTAINSROOT' // 'SET_CONTAINSROOT'
@ -64,7 +56,6 @@
//==========<preset>=========== //==========<preset>===========
// (1) the backbone AP // (1) the backbone AP
#if 0 #if 0
#define DISABLE_I2C_REQ
#define SET_CONTAINSROOT #define SET_CONTAINSROOT
// (2) osc client (the ROOT) // (2) osc client (the ROOT)
#elif 0 #elif 0
@ -77,7 +68,6 @@
// (3) sampler client // (3) sampler client
#elif 1 #elif 1
#define DISABLE_AP #define DISABLE_AP
#define DISABLE_I2C_REQ
// //
#endif #endif
//==========</preset>========== //==========</preset>==========
@ -88,6 +78,7 @@
#define MESH_PORT 5555 #define MESH_PORT 5555
#define MESH_CHANNEL 5 #define MESH_CHANNEL 5
#define LONELY_TO_DIE (1000) #define LONELY_TO_DIE (1000)
#define MONITORING_SERIAL (Serial1) //you should use, external uart2usb converter to monitor messages...
//============</parameters>=========== //============</parameters>===========
// //
@ -116,8 +107,8 @@
//arduino //arduino
#include <Arduino.h> #include <Arduino.h>
//i2c //protocol
#include <Wire.h> // #include <Wire.h>
#include "../post.h" #include "../post.h"
//painlessmesh //painlessmesh
@ -165,14 +156,14 @@ void nothappyalone() {
// oh.. i m lost the signal(==connection) // oh.. i m lost the signal(==connection)
if (isConnected_prev != isConnected && isConnected == false) { if (isConnected_prev != isConnected && isConnected == false) {
lonely_time_start = millis(); lonely_time_start = millis();
Serial.println("oh.. i m lost!"); MONITORING_SERIAL.println("oh.. i m lost!");
} }
// .... how long we've been lonely? // .... how long we've been lonely?
if (isConnected == false) { if (isConnected == false) {
if (millis() - lonely_time_start > LONELY_TO_DIE) { if (millis() - lonely_time_start > LONELY_TO_DIE) {
// okay. i m fed up. bye the world. // okay. i m fed up. bye the world.
Serial.println("okay. i m fed up. bye the world."); MONITORING_SERIAL.println("okay. i m fed up. bye the world.");
Serial.println(); MONITORING_SERIAL.println();
#if defined(ESP8266) #if defined(ESP8266)
ESP.reset(); ESP.reset();
#elif defined(ESP32) #elif defined(ESP32)
@ -191,61 +182,58 @@ void nothappyalone() {
Task nothappyalone_task(100, TASK_FOREVER, &nothappyalone); // by default, ENABLED. Task nothappyalone_task(100, TASK_FOREVER, &nothappyalone); // by default, ENABLED.
//task #2 : regular post collection //task #2 : regular post collection
#if !defined(DISABLE_I2C_REQ)
void collect_post() { void collect_post() {
// //
static char letter_outro[POST_BUFF_LEN] = "................................"; static char letter_outro[POST_BUFF_LEN] = "................................";
// ask a letter and collect the feedback.
Wire.requestFrom(I2C_ADDR, POST_LENGTH);
// error flag // error flag
bool letter_is_good = false; bool letter_is_good = false;
// check the first byte // check the first byte
char first = '.'; char first = '.';
// automatically match start byte. // automatically match start byte.
while (Wire.available()) { while (Serial.available()) {
first = Wire.read(); first = Serial.read();
if (first == '[') { if (first == '[' || first == '{') {
// client want to give me a letter. // client want to give me a letter or hello.
letter_outro[0] = first; letter_outro[0] = first;
// matched! // matched!
letter_is_good = true; letter_is_good = true;
break; break;
} else if (first == ' ') { } else if (first == ' ') {
// client says nothing to send. // client says nothing to send.
Serial.print("."); // nothing to send. MONITORING_SERIAL.print("."); // nothing to send.
return; return;
} }
} }
// //
if (letter_is_good == false) { if (letter_is_good == false) {
// no more letters, but no valid char. // no more letters, but no valid char.
Serial.print("?"); // wrong client. MONITORING_SERIAL.print("?"); // wrong client.
return; return;
} else if (letter_is_good == true) { } else if (letter_is_good == true) {
// get more contents // get more contents
for (int i = 1; i < (POST_LENGTH-1); i++) { for (int i = 1; i < (POST_LENGTH-1); i++) {
if (Wire.available()) { if (Serial.available()) {
letter_outro[i] = Wire.read(); letter_outro[i] = Serial.read();
} else { } else {
// hmm.. letter is too short. // hmm.. letter is too short.
letter_outro[i] = '.'; // fill-out with dots. letter_outro[i] = '.'; // fill-out with dots.
Serial.print("$"); // too $hort msg. MONITORING_SERIAL.print("$"); // too $hort msg.
letter_is_good = false; letter_is_good = false;
} }
} }
// the last byte // the last byte
char last = '.'; char last = '.';
if (Wire.available()) { if (Serial.available()) {
letter_outro[POST_LENGTH-1] = last = Wire.read(); letter_outro[POST_LENGTH-1] = last = Serial.read();
if (last != ']') { if (last != ']' && last != '}') {
// hmm.. last byte is strange // hmm.. last byte is strange
Serial.print("#"); // last byte error. MONITORING_SERIAL.print("#"); // last byte error.
letter_is_good = false; letter_is_good = false;
} }
} else { } else {
// hmm.. letter is too short. // hmm.. letter is too short.
letter_outro[POST_LENGTH-1] = '.'; // fill-out with dots. letter_outro[POST_LENGTH-1] = '.'; // fill-out with dots.
Serial.print("$"); // too $hort msg. MONITORING_SERIAL.print("$"); // too $hort msg.
letter_is_good = false; letter_is_good = false;
} }
// terminal char. // terminal char.
@ -258,33 +246,30 @@ void collect_post() {
// or, post it. // or, post it.
if (isConnected == true) { if (isConnected == true) {
mesh.sendBroadcast(String(letter_outro)); mesh.sendBroadcast(String(letter_outro));
Serial.print("sendBroadcast: "); MONITORING_SERIAL.print("sendBroadcast: ");
Serial.println(letter_outro); MONITORING_SERIAL.println(letter_outro);
} else { } else {
Serial.print("_"); // disconnected. MONITORING_SERIAL.print("_"); // disconnected.
} }
} }
Task collect_post_task(10, TASK_FOREVER, &collect_post, &runner, true); // by default, ENABLED Task collect_post_task(10, TASK_FOREVER, &collect_post, &runner, true); // by default, ENABLED
//MAYBE... 10ms is too fast? move this to the loop() then? //MAYBE... 10ms is too fast? move this to the loop() then?
#endif
// mesh callbacks // mesh callbacks
void receivedCallback(uint32_t from, String & msg) { // REQUIRED void receivedCallback(uint32_t from, String & msg) { // REQUIRED
Serial.print("got msg.: "); MONITORING_SERIAL.print("got msg.: ");
Serial.println(msg); MONITORING_SERIAL.println(msg);
// truncate any extra. letters. // truncate any extra. letters.
msg = msg.substring(0, POST_LENGTH); // (0) ~ (POST_LENGTH-1) msg = msg.substring(0, POST_LENGTH); // (0) ~ (POST_LENGTH-1)
// send whatever letter we postmans trust other postman. // send whatever letter we postmans trust other postman.
Wire.beginTransmission(I2C_ADDR);
#if defined(ARDUINO_NodeMCU_32S) #if defined(ARDUINO_NodeMCU_32S)
Wire.write((const uint8_t*)msg.c_str(), POST_LENGTH); Serial.write((const uint8_t*)msg.c_str(), POST_LENGTH);
#else #else
Wire.write(msg.c_str(), POST_LENGTH); Serial.write(msg.c_str(), POST_LENGTH);
#endif #endif
Wire.endTransmission();
} }
void changedConnectionCallback() { void changedConnectionCallback() {
Serial.println(mesh.getNodeList().size()); MONITORING_SERIAL.println(mesh.getNodeList().size());
// check status -> modify status LED // check status -> modify status LED
if (mesh.getNodeList().size() > 0) { if (mesh.getNodeList().size() > 0) {
// (still) connected. // (still) connected.
@ -292,7 +277,7 @@ void changedConnectionCallback() {
statusblinks.set(LED_PERIOD, 2, &taskStatusBlink_slowblink_insync); statusblinks.set(LED_PERIOD, 2, &taskStatusBlink_slowblink_insync);
// statusblinks.set(0, 1, &taskStatusBlink_steadyOff); // statusblinks.set(0, 1, &taskStatusBlink_steadyOff);
statusblinks.enable(); statusblinks.enable();
Serial.println("connected!"); MONITORING_SERIAL.println("connected!");
// //
isConnected = true; isConnected = true;
runner.addTask(nothappyalone_task); runner.addTask(nothappyalone_task);
@ -305,13 +290,12 @@ void changedConnectionCallback() {
// //
isConnected = false; isConnected = false;
} }
// let I2C device know //
///// MONITORING_SERIAL.println("hi. client, we ve got a change in the net.");
Serial.println("hi. client, we ve got a change in the net.");
} }
void newConnectionCallback(uint32_t nodeId) { void newConnectionCallback(uint32_t nodeId) {
Serial.println(mesh.getNodeList().size()); MONITORING_SERIAL.println(mesh.getNodeList().size());
Serial.println("newConnectionCallback."); MONITORING_SERIAL.println("newConnectionCallback.");
changedConnectionCallback(); changedConnectionCallback();
} }
@ -344,7 +328,7 @@ void setup() {
mesh.onReceive(&receivedCallback); mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback); mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback); mesh.onChangedConnections(&changedConnectionCallback);
Serial.println(mesh.getNodeList().size()); MONITORING_SERIAL.println(mesh.getNodeList().size());
//tasks //tasks
runner.addTask(statusblinks); runner.addTask(statusblinks);
@ -388,8 +372,11 @@ void setup() {
// nodeId (hex) : 2D370A07 // nodeId (hex) : 2D370A07
// MAC : B6, E6, 2D, 37, A, 7 // MAC : B6, E6, 2D, 37, A, 7
//i2c master //esp8266(serial.swap) <-> teensy(serial3)
Wire.begin(); delay(1000);
Serial.swap();
delay(100);
// Serial.println("hi, uart. ping?");
} }
void loop() { void loop() {