Control-Surface
Control-Surface copied to clipboard
2 different Banks saving data on SD with Json Structure
First of everything, Pieter thanks for your wonderful job. I Am Danilo from Italy and I have to ask you help for an ideas that arrived from problems during music live performance . I am not a musician (hobby), I am not a programmer (hobby), and I have few times to do a lot of thing that I have in my head. I programmed at university and sometimes at work but when I programmed first time there was the "basic" program language on so I m new in this kind of wonderful system like Arduino. Well, it's the first time I write here and I solved a lot of problems reading here, so thanks also to everyone. My problem is: how I can use two different banks (like bank1 and bank2) for two arrays of encoders saving data on a json structure and alter on a sd?
My code is a mix of your code and other code around the network... I modified also your code (sorry don't be angry and I hope that I done good job...)
Anyways the code below is only for one encoder one bank: (I USE an ARDUINO MEGA... because the code need more memory )
#include <Control_Surface.h> // Include the Control Surface library
#include <SPI.h>
#include <ArduinoJson.h>
#include <SD.h>
#define SS 53 //Pin del SS del SD Reader
// variabile per la definizione del bottone di write e read
#define write 3 //Pin del pulsante per scrivere i data su SD
#define read 2 //Pin del pulsante per leggere i data salvati su SD
// definisco i Pin del RGBLed per la SD
#define RgbLedRedPin 54 //A0 analogPin
#define RgbLedGreenPin 55 //A1 analogPin
#define RgbLedBluePin 56 //A2 analogPin
//variabili per il debounce dei pulsanti
long Debounce_delay = 100;
long t1 = 0;
const char *filename = "MONITORS.TXT"; // <- SD library uses 8.3 filenames
// Creo l'oggetto JSON
DynamicJsonDocument doc(1024);
JsonObject obj;
File myFileSDCart;
JsonObject getJSonFromFile(DynamicJsonDocument *doc, String filename, bool forceCleanONJsonError = true )
{
myFileSDCart = SD.open(filename); // open the file for reading:
if (myFileSDCart) { // read from the file until there's nothing else in it:
DeserializationError error = deserializeJson(*doc, myFileSDCart);
if (error) {
Serial.print(F("Error parsing JSON ")); // if the file didn't open, print an error:
Serial.println(error.c_str());
if (forceCleanONJsonError){
return doc->to<JsonObject>();
}
}
myFileSDCart.close(); // close the file:
return doc->as<JsonObject>();
} else {
Serial.print(F("Error opening (or file not exists) ")); // if the file didn't open, print an error:
Serial.println(filename);
Serial.println(F("Empty json created"));
return doc->to<JsonObject>();
}
}
// Custom callback to handle output for a selector.
class MySelectorCallback {
uint8_t pickedColor[10][3] ={ // defined Bank Colors R,G,B
{255, 0, 0}, //rosso
{200,100, 53}, //giallo limone
{ 0, 0,150}, //blu
{ 0,100, 0}, //verde
{255, 0,255}, //magenta
{ 10, 50,255}, //azzurro
{255,255,255}, //bianco
{100,100,255}, //celeste
{ 0, 0, 0}, //SPENTO
{128, 0,128}, //viola
};
public:
// Constructor
MySelectorCallback(pin_t redLED, pin_t greenLED, pin_t blueLED)
: redLED(redLED), greenLED(greenLED), blueLED(blueLED) {}
// Begin function is called once by Control Surface.
// Use it to initialize everything.
void begin() { //PinMode deleted because are AnalogPin not Digital
show(0);
}
// Update function is called continuously by Control Surface.
// Use it to implement things like fading, blinking ...
void update() {}
// Update function with arguments is called when the setting
// changes.
// Use it to update the LEDs.
void update(setting_t oldSetting, setting_t newSetting) {
(void) oldSetting; // unused in this example
show(newSetting);
}
private:
// Show the color of the given setting.
void show(setting_t setting) {
uint8_t colorRed = getColorRed(setting);
uint8_t colorGreen = getColorGreen(setting);
uint8_t colorBlue = getColorBlue(setting);
analogWrite(redLED, colorRed); //if were digital pin i should use DigitalWrite
analogWrite(greenLED, colorGreen);
analogWrite(blueLED, colorBlue);
}
// Convert the given setting to a 3-bit RGB color value.
uint8_t getColorRed(setting_t setting) {
switch (setting) {
case 0: return pickedColor[setting][0];
case 1: return pickedColor[setting][0];
case 2: return pickedColor[setting][0];
case 3: return pickedColor[setting][0];
case 4: return pickedColor[setting][0];
case 5: return pickedColor[setting][0];
case 6: return pickedColor[setting][0];
case 7: return pickedColor[setting][0];
// case 8: return pickedColor[setting][0];
default: return 0;
}
}
uint8_t getColorGreen(setting_t setting) {
switch (setting) {
case 0: return pickedColor[setting][1];
case 1: return pickedColor[setting][1];
case 2: return pickedColor[setting][1];
case 3: return pickedColor[setting][1];
case 4: return pickedColor[setting][1];
case 5: return pickedColor[setting][1];
case 6: return pickedColor[setting][1];
case 7: return pickedColor[setting][1];
// case 8: return pickedColor[setting][1];
default: return 0;
}
}
uint8_t getColorBlue(setting_t setting) {
switch (setting) {
case 0: return pickedColor[setting][2];
case 1: return pickedColor[setting][2];
case 2: return pickedColor[setting][2];
case 3: return pickedColor[setting][2];
case 4: return pickedColor[setting][2];
case 5: return pickedColor[setting][2];
case 6: return pickedColor[setting][2];
case 7: return pickedColor[setting][2];
// case 8: return pickedColor[setting][2];
default: return 0;
}
}
private:
// Member variables to remember the pin numbers of the LEDs.
pin_t redLED, greenLED, blueLED;
};
// :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: //
//USBMIDI_Interface midi;
USBDebugMIDI_Interface midi;
// Create 8 banks with one track per bank.
Bank<8> bank(1); // 8 musicians, 1 track (encoder) for each musician
// Create a selector that uses our custom callback, to control the bank.
GenericIncrementDecrementSelector<8, MySelectorCallback> selector {
bank, // bank to manage
{5, 6, 7}, // red, green, blue LED pins
// (this is the MySelectorCallback constructor defined above)
{8, 9}, // incr/decr button pins
Wrap::Wrap, // wrap around when reaching setting 6
};
// Handy type alias
using CCAbsEnc = Bankable::CCAbsoluteEncoder<8>;
// Instantiate a CCAbsoluteEncoder object
CCAbsEnc enc[] = {
{
{bank, BankType::CHANGE_ADDRESS},
{22, 23}, // pins
{7,CHANNEL_5}, // MIDI address (CC number + optional channel)
1, // optional multiplier if the control isn't fast enough
},
};
void setup() {
pinMode(RgbLedRedPin, OUTPUT);
pinMode(RgbLedGreenPin, OUTPUT);
pinMode(RgbLedBluePin, OUTPUT);
pinMode(write, INPUT_PULLUP); // Inizializiamo il pin del pulsante di write
pinMode(read, INPUT_PULLUP); // Inizializiamo il pin del pulsante di read
Control_Surface.begin(); // Initialize Control Surface
Serial.begin(115200);
while (!SD.begin(SS)) { // Initialize SD library
Serial.println("Failed");
Serial.println("to initialize");
Serial.println("SD library");
for (int i =0; i<4; i++){
BlinkSdLed(0);
delay(200);
BlinkSdLed(1);
delay(200);
BlinkSdLed(2);
delay(200);
}
BlinkSdLed(0);
}
Serial.println("SD library");
Serial.println("initialized");
Serial.println("READY TO WORK!");
BlinkSdLed(0);
delay(300);
BlinkSdLed(1);
delay(300);
BlinkSdLed(2);
delay(300);
BlinkSdLed(1);
readData();
}
void loop() {
Control_Surface.loop(); // Update the Control Surface
readFromSD();
writeOnSD();
}
void BlinkSdLed(int color)
{
switch(color) {
case 0:
digitalWrite(RgbLedRedPin,255);
digitalWrite(RgbLedGreenPin,0);
digitalWrite(RgbLedBluePin,0);
break;
case 1:
digitalWrite(RgbLedRedPin,0);
digitalWrite(RgbLedGreenPin,255);
digitalWrite(RgbLedBluePin,0);
break;
case 2:
digitalWrite(RgbLedRedPin,0);
digitalWrite(RgbLedGreenPin,0);
digitalWrite(RgbLedBluePin,255);
break;
}
}
void writeOnSD(){
if (millis() - t1 > Debounce_delay){
if (digitalRead(write)==LOW) {
obj = getJSonFromFile(&doc, filename);
for (int j = 0; j < 8; j++) {
obj[F("encVals")][j] = enc[0].getValue(j);
}
t1 = millis();
boolean isSaved = saveJSonToAFile(&doc, filename);
if (isSaved){
BlinkSdLed(0);
Serial.println("File saved!");
delay(300);
BlinkSdLed(1);
}else{
BlinkSdLed(0);
Serial.println("Error on save File!");
for (int i =0; i<4; i++){
BlinkSdLed(1);
delay(200);
BlinkSdLed(2);
delay(200);
BlinkSdLed(0);
delay(200);
}
BlinkSdLed(1);
}
}
}
}
void readData(){
obj = getJSonFromFile(&doc, filename); // riempio l'array dei valori salvati e letti da SD attraverso la struttura Json
for (int j=0; j < 8; j++) {
enc[0].setValue(obj[F("encVals")][j],j);
}
}
void readFromSD(){
if (millis() - t1 > Debounce_delay){
if (digitalRead(read)==LOW) {
BlinkSdLed(0);
Serial.println("READ DATA...!");
delay(300);
BlinkSdLed(1);
t1 = millis();
readData();
}
}
}
bool saveJSonToAFile(DynamicJsonDocument *doc, String filename) {
SD.remove(filename);
myFileSDCart = SD.open(filename, FILE_WRITE); // open the file. note that only one file can be open at a time, so you have to close this one before opening another.
if (myFileSDCart) {
serializeJson(*doc, myFileSDCart);
myFileSDCart.close(); // close the file:
return true;
} else {
return false;
}
}
Everything work good in this situation... the Jason structure is something like that: {encVals:{64,64,64,64,64,64,64,64}}
where I save on a file called MONITORS.TXT this structure and I call it every time I need (with a button) (not yet implemented but already ready because used in a previous release of this project) and when I turn on Arduino. 8 values are the 8 banks for 1 encoder... so I need a structure with 11 encoders, so 88 of that structure values... so ... with the code of
for (int j=0; j < 8; j++) {
enc[0].setValue(obj[F("encVals")][j],j);
}
I read values from the json structure
with this code
for (int j = 0; j < 8; j++) {
obj[F("encVals")][j] = enc[0].getValue(j);
}
I write values in the json structure later I write date on the SD serializing and deserializing the structure on the SD... Ff course if I need for 11 encoders I need to do another for cycle to from 0 to 11 to save the other encoders value.
well now I have connected at the same Mega other 8 encoders with 9 banks so I will need something like that
Bank<9> bank(8);
// Create a selector that uses our custom callback, to control the bank.
GenericIncrementDecrementSelector<8, MySelectorCallback> selector1 {
bank1, // bank to manage
......
};
// Handy type alias
using CCAbsEnc1 = Bankable::CCAbsoluteEncoder<9>;
CCAbsEnc1 enc1[] = {
{
{bank1, BankType::CHANGE_ADDRESS},
.....
};
probably I need something like that but my problem is
for (int j=0; j < 8; j++) {
enc[0].setValue(obj[F("encVals")][j],j);
}
I read values from the json structure
with this code
for (int j = 0; j < 8; j++) {
obj[F("encVals")][j] = enc[0].getValue(j);
}
how I can change this code to identify the two different banks?
Thanks for the help... thanks a lot