Hello to all! Having a problem understanding the best way to go about this project so I'll start with an explanation of what I'm trying to do first.
I want to create a usb midi controller to communicate with three separate guitar pedals, which will select presets on each of the pedals 0-99.
I've chosen a Teensy 2.0 as it can work as a usb midi interface.
One foot switch selects A, B or C (guitar pedals) and the other two foot switches control the presets for each pedal 0-99.
So far with the code I have, I can select A B or C with one button but I'm unable to select 0-99 for each of those with the other two buttons.
Is Switch Case a good option for this project? And if so, should I use if statements within each case or refer to a function in the main loop for the button presses instead?
If I can get this working as described then I'll add usb midi functions afterwards.
Any help much appreciated.
#include "TM1637.h" // include TM1637 library
#define CLK 2 // define TM1637 clock pin
#define DIO 3 // define TM1637 data pin
// initialize the TM1637 library
TM1637 tm1637(CLK, DIO);
//buttons for preset selection
//last 2 digits of tm1637 display (0-99)
#define UP 4 // define up button pin
#define DN 5 // define down button pin
//button for "A" "b" or "C" selection
//1st digit of TM1637 display
const int btn = 6;
int selector = 0;
boolean isPressed = false;
int num = 0, prev_num = 1;
void setup() {
Serial.begin(9600);
pinMode(btn, INPUT);
pinMode(UP, INPUT);
pinMode(DN, INPUT);
// initialize the TM1637 display
tm1637.init();
// set display brightness (from 0 to 7)
tm1637.set(3);
}
void loop ()
{
if (digitalRead(btn) == LOW && isPressed == false ) //button is pressed AND this is the first digitalRead() that the button is pressed
{
isPressed = true; //set to true, so this code will not run again until button released
doSwitchStatement(); // a call to a separate function that performs the switch statement and subsequent evoked code
selector++; // this is done after the doSwitchStatement(), so case 0 will be executed on the first button press
if (selector > 2) {
selector = 0;
}
// selector = (selector+1) % 4; // does the same, without if-statement
} else if (digitalRead(btn) == HIGH)
{
isPressed = false; //button is released, variable reset
}
}
void numSelect () {
if(num != prev_num)
{ // if the displayed (current) number was changed
prev_num = num; // save current value of 'num'
// print all data
//tm1637.display(0, num/1000); // print thousands digit //0,10 will make "A"
//tm1637.display(1, num/100 % 10); // print hundreds digit
tm1637.display(2, num/10 % 10); // print tens digit
tm1637.display(3, num% 10); // print ones digit
delay(200); // wait 200 milliseconds
}
if( digitalRead(UP) )
{ // if the UP button is presses
num++; // increment 'num'
if(num > 99) //99
num = 0;
Serial.println("UP");
}
if( digitalRead(DN) )
{ // if the DN button is presses
num--; // decrement 'num'
if(num < 0)
num = 99; //99
Serial.println("DN");
}
}
void doSwitchStatement() {
switch (selector) {
case 0:
Serial.println("Case 0");
tm1637.display(0, 10);
numSelect();
break;
case 1:
Serial.println("Case 1");
tm1637.display(0, 11);
numSelect();
break;
case 2:
Serial.println("Case 2");
tm1637.display(0, 12);
numSelect();
break;
}
}
With some further tricking I've incorporated the function numSelect into the main loop and can select 0-99 as well as A B & C but now i need to keep these selections within the Teensy memory so that they can be recalled.
#include "TM1637.h" // include TM1637 library
#define CLK 2 // define TM1637 clock pin
#define DIO 3 // define TM1637 data pin
// initialize the TM1637 library
TM1637 tm1637(CLK, DIO);
//buttons for preset selection
//last 2 digits of tm1637 display (0-99)
#define UP 4 // define up button pin
#define DN 5 // define down button pin
//button for "A" "b" or "C" selection
//1st digit of TM1637 display
const int btn = 6;
int selector = 0;
boolean isPressed = false;
int num = 0, prev_num = 1;
void setup() {
Serial.begin(9600);
pinMode(btn, INPUT);
pinMode(UP, INPUT);
pinMode(DN, INPUT);
// initialize the TM1637 display
tm1637.init();
// set display brightness (from 0 to 7)
tm1637.set(3);
}
void loop ()
{
if (digitalRead(btn) == LOW && isPressed == false ) //button is pressed AND this is the first digitalRead() that the button is pressed
{
isPressed = true; //set to true, so this code will not run again until button released
doSwitchStatement(); // a call to a separate function that performs the switch statement and subsequent evoked code
selector++; // this is done after the doSwitchStatement(), so case 0 will be executed on the first button press
if (selector > 2) {
selector = 0;
}
// selector = (selector+1) % 4; // does the same, without if-statement
} else if (digitalRead(btn) == HIGH)
{
isPressed = false; //button is released, variable reset
}
if(num != prev_num)
{ // if the displayed (current) number was changed
prev_num = num; // save current value of 'num'
// print all data
//tm1637.display(0, num/1000); // print thousands digit //0,10 will make "A"
//tm1637.display(1, num/100 % 10); // print hundreds digit
tm1637.display(2, num/10 % 10); // print tens digit
tm1637.display(3, num% 10); // print ones digit
delay(200); // wait 200 milliseconds
}
if( digitalRead(UP) )
{ // if the UP button is presses
num++; // increment 'num'
if(num > 99) //99
num = 0;
Serial.println(num);
}
if( digitalRead(DN) )
{ // if the DN button is presses
num--; // decrement 'num'
if(num < 0)
num = 99; //99
Serial.println(num);
}
}
void doSwitchStatement() {
switch (selector) {
case 0:
Serial.println("Case 0");
tm1637.display(0, 10);
//numSelect();
break;
case 1:
Serial.println("Case 1");
tm1637.display(0, 11);
//numSelect();
break;
case 2:
Serial.println("Case 2");
tm1637.display(0, 12);
//numSelect();
break;
}
}
Thanks jflaros. I tried your compressed switch statement but calling the "numSelect();" isn't working. It's only working when I incorporate it into the main loop. I'll look into the EEPROM library now...
I've done away with the switch case altogether and kept all buttons in the main loop. Now to implement EEPROM to store settings for recall.
#include "TM1637.h" // include TM1637 library
#include <EEPROM.h>
#define CLK 2 // define TM1637 clock pin
#define DIO 3 // define TM1637 data pin
// initialize the TM1637 library
TM1637 tm1637(CLK, DIO);
//buttons for preset selection
//last 2 digits of tm1637 display (0-99)
#define UP 4 // define up button pin
#define DN 5 // define down button pin
//button for "A" "b" or "C" selection
//1st digit of TM1637 display
const int btn = 6;
int num = 0, prev_num = 1;
int let = 0, prev_let = 1;
void setup() {
Serial.begin(9600);
pinMode(btn, INPUT);
pinMode(UP, INPUT);
pinMode(DN, INPUT);
// initialize the TM1637 display
tm1637.init();
// set display brightness (from 0 to 7)
tm1637.set(3);
}
void loop ()
{
if (num != prev_num)
{ // if the displayed (current) number was changed
prev_num = num; // save current value of 'num'
// print all data
tm1637.display(2, num / 10 % 10); // print tens digit
tm1637.display(3, num % 10); // print ones digit
delay(200); // wait 200 milliseconds
}
if (let != prev_let)
{ // if the displayed (current) number was changed
prev_let = let; // save current value of 'let'
// print all data
tm1637.display(0, (let + 10)); //this gives me 10, 11 & 12 (A,b & C)
delay(200); // wait 200 milliseconds
}
if ( digitalRead(UP) )
{ // if the UP button is presses
num++; // increment 'num'
if (num > 99) //99
num = 0;
Serial.println(num);
}
if ( digitalRead(DN) )
{ // if the DN button is presses
num--; // decrement 'num'
if (num < 0)
num = 99; //99
Serial.println(num);
}
if ( digitalRead(btn) )
{ // if the UP button is presses
let++; // increment 'num'
if (let > 2)
let = 0;
Serial.println(let);
}
}
Just reading up about writing to EEPROM and see that there are a limited amount of times you can write to it, 100,000 times or so. Whilst this isn't an issue initially, it may be some years down the road. I've read that I can save settings when powering down which will extend the life of the EEPROM.
My question now is how to differentiate A 0-99, B 0-99 and C 0-99 from each other and allocate a memory for each combination.
For example, I may select A3 for pedal "A" this tells the pedal to select preset 3 in the pedal itself. I may then select B20 for pedal B and so on. The important thing is that when I switch back to pedal "A", it needs to return to its last memory slot, "3"! This would mean that with every selection i would have to write to EEPROM, no?
The alternative I guess is to use the UP and DN buttons to select only and a long press would then write that selection to memory?
Any ideas on this would be very apreciated...
Thinking about it some more, I realise i only need to save the current settings when I switch between bank A B or C. This should make things simpler...
You could keep all settings in memory and only write to EEPROM whenever the device is shut down (in a controlled way), or when a save operation is requested.
If you use the put() function to write to EEPROM, the EEPROM memory will only be written to if the data to be written is different from the current content.
Easier in theory than practice...
I believe I need to store three numbers to an array. These will be stored each time I press "btn". I'm not sure I can find an example of this anywhere that I can understand. So far I have "int storedValues[3];" for my array. Next I have to place something like this into its correct place " ```
storedValues[] = digitalRead(btn);
if ( digitalRead(btn) )
{ // if the btn button is presses
let++; // increment 'let'
if (let > 2)
let = 0;
Serial.println(let);
storedValues[btn] = digitalRead(btn);
Serial.println(storedValues[let]);
}
}
Of course this is completely wrong and doesn't work.
Could anyone please advise on how to make this work?
Well I have managed to store 0-99 in each bank (A B & C) and recall them with each successive btn press. However, on the fourth press it doesn't recall because the the array's elements are being replaced always.
#include "TM1637.h" // include TM1637 library
#include <EEPROM.h>
#define CLK 2 // define TM1637 clock pin
#define DIO 3 // define TM1637 data pin
// initialize the TM1637 library
TM1637 tm1637(CLK, DIO);
//buttons for preset selection
//last 2 digits of tm1637 display (0-99)
#define UP 4 // define up button pin
#define DN 5 // define down button pin
//button for "A" "b" or "C" selection
//1st digit of TM1637 display
const int btn = 6;
int num = 0, prev_num = 1;
int let = 0, prev_let = 1;
const unsigned int numReadings = 3;
int storedValues[numReadings];
void setup() {
Serial.begin(9600);
pinMode(btn, INPUT);
pinMode(UP, INPUT);
pinMode(DN, INPUT);
// initialize the TM1637 display
tm1637.init();
// set display brightness (from 0 to 7)
tm1637.set(3);
}
void loop ()
{
if (num != prev_num)
{ // if the displayed (current) number was changed
prev_num = num; // save current value of 'num'
// print all data
Serial.println(num);
tm1637.display(2, num / 10 % 10); // print tens digit
tm1637.display(3, num % 10); // print ones digit
delay(200); // wait 200 milliseconds
}
if (let != prev_let)
{ // if the displayed (current) number was changed
prev_let = let; // save current value of 'let'
// print all data
//Serial.println(let);
tm1637.display(0, (let + 10)); //this gives me 10, 11 & 12 (A,b & C)
delay(200); // wait 200 milliseconds
}
if ( digitalRead(UP) )
{ // if the UP button is presses
num++; // increment 'num'
if (num > 99) //99
num = 0;
}
if ( digitalRead(DN) )
{ // if the DN button is presses
num--; // decrement 'num'
if (num < 0)
num = 99; //99
}
storedValues[let] = num;
if ( digitalRead(btn) )
{ // if the btn button is presses
let++; // increment 'let'
if (let >= numReadings)
let = 0;
//Serial.println(let);
Serial.println(storedValues[let]);
delay(100);
}
}
I'm guessing now that I will need to use EEPROM so as to recall with btn only those numbers that I specifically save....?
This isn't a problem I guess but is there another way to hold those saved numbers in an array and even rewrite them (save) to the same array if needed? Am I looking to store elements in specific positions of the array only?
Either can work. I would be inclined to save to the array until you are satisfied with the setup and then trigger the write to EEPROM.
FRAM is pretty cheap and the number of writes is effectively unlimited. If you got one, you could forget about being careful not to wear out the EEPROM.
Just thinking out loud here. I'm assuming a four-digit display.
Designate the 1000s digit as a 'home' position. Put some character you like in there.
When the 'select' switch is pressed the 1000s character goes off and the 100's DP goes on to indicate pedal A is active. Display pedal A's value and adjust up/dn with the other two switches.
Press select again and 100s DP goes off, 10s DP goes on and pedal B is adjusted (or not) as above.
Press select again and 10s DP goes off, 1's DP goes on. Adjust pedal C as before.
Press select once more and all DPs are set off and the home character is displayed.
If on home digit for X milliseconds trigger a save of values if any of them have changed.
This is a nice idea dougp. An issue though would be the amount of presets available when your down to 10's and 1's for pedals B and C. I'm looking to use up to 100 presets for each of the three pedals.
So far I've managed to save presets to a separate array using an extra button "Sv"... Which is no small feat for me!
#include "TM1637.h" // include TM1637 library
#include <EEPROM.h>
#define CLK 2 // define TM1637 clock pin
#define DIO 3 // define TM1637 data pin
// initialize the TM1637 library
TM1637 tm1637(CLK, DIO);
//buttons for preset selection
//last 2 digits of tm1637 display (0-99)
#define UP 4 // define up button pin
#define DN 5 // define down button pin
//button for "A" "b" or "C" selection
//1st digit of TM1637 display
const int btn = 6;
//button to save settings
const int Sv = 9;
int buttonState = 0;
int num = 0, prev_num = 1;
int let = 0, prev_let = 1;
int i = 0, prev_i = 1;
const unsigned int numReadings = 3;
int storedValues[numReadings];
int Saves[numReadings];
void setup() {
Serial.begin(9600);
pinMode(btn, INPUT);
pinMode(UP, INPUT);
pinMode(DN, INPUT);
pinMode(Sv, INPUT);
// initialize the TM1637 display
tm1637.init();
// set display brightness (from 0 to 7)
tm1637.set(3);
}
void loop ()
{
if (num != prev_num)
{ // if the displayed (current) number was changed
prev_num = num; // save current value of 'num'
// print all data
Serial.println(num);
tm1637.display(2, num / 10 % 10); // print tens digit
tm1637.display(3, num % 10); // print ones digit
delay(200); // wait 200 milliseconds
}
if (let != prev_let)
{ // if the displayed (current) number was changed
prev_let = let; // save current value of 'let'
// print all data
//Serial.println(let);
tm1637.display(0, (let + 10)); //this gives me 10, 11 & 12 (A,b & C)
delay(200); // wait 200 milliseconds
}
if (i != prev_i)
{ // if the displayed (current) number was changed
prev_i = i; // save current value of 'let'
// print all data
//Serial.println(i);
//Serial.println(Saves[i]);
delay(200); // wait 200 milliseconds
}
if ( digitalRead(UP) )
{ // if the UP button is presses
num++; // increment 'num'
if (num > 99) //99
num = 0;
}
if ( digitalRead(DN) )
{ // if the DN button is presses
num--; // decrement 'num'
if (num < 0)
num = 99; //99
}
//storedValues[let] = num;
if ( digitalRead(btn) )
{ // if the btn button is presses
let++; // increment 'let'
if (let > 2)
let = 0;
//Serial.println(let);
//Serial.println(storedValues[let]);
Serial.println(Saves[let]);
delay(100);
}
buttonState = digitalRead(Sv);
if (buttonState == HIGH)
{
i++;
if (i > 2)
i = 0;
Saves[i] = num;
}
}
However, of course the saved presets won't display on the tm1637 as I cycle through them. Can anyone help me with this please?