Hi all, I am in the early stages of making an Arduino controlled signal generator with a 128x64 OLED screen, a rotary encoder and some tactile push buttons. I have yet to add the actual signal generator chip - I am simply working on the display and interface code at the moment.
Basically you change the frequency by using a left and right button to select one of five digits (since the frequency can change from 00000Hz to 99999Hz) you then rotate the rotary encoder to count the selected digit up or down. Here is the full code listing:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Rotary.h>
Rotary r = Rotary(2, 3);
Adafruit_SSD1306 display(4);
// inputs / outputs
const int inputA = 2;
const int inputB = 3;
const int leftButton = 12;
const int rightButton = 11;
// variables
unsigned long frequency = 10;
int digitToModify = 0;
bool buttonPressed = false;
bool countUp = false;
bool countDown = false;
void setup(){
// Button setup
pinMode(leftButton, INPUT);
pinMode(rightButton, INPUT);
// Rotary encoder interrupt setup
PCICR |= (1 << PCIE2);
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
// OLED display Setup
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x64)
display.setTextColor(WHITE);
display.clearDisplay();
}
void loop(){
updateFrequency();
checkButton();
updateDisplay();
}
void updateDisplay(){
display.clearDisplay();
display.setTextSize(2);
display.setCursor(10,0);
display.print("Frequency");
display.setTextSize(3);
display.setCursor(0,30);
// pad with leading zero's to ensure the frequency always displays 5 digits
if(frequency < 10000) display.print("0");
if(frequency < 1000) display.print("0");
if(frequency < 100) display.print("0");
if(frequency < 10) display.print("0");
display.print(frequency);
display.print("Hz");
//draw a line underneath the digit you want to modify
display.drawLine(((4 - digitToModify) * 18), 53, 14 + ((4 - digitToModify) * 18), 53, WHITE);
display.display();
}
void updateFrequency(){
if(countUp == true){
countUp = false;
if(frequency + pow(10, digitToModify) <= 99999) frequency = frequency + pow(10, digitToModify);
}
else if(countDown == true){
countDown = false;
if(frequency - pow(10, digitToModify) > 0) frequency = frequency - pow(10, digitToModify);
}
}
void checkButton(){
// check for a left button press
if(digitalRead(leftButton) == 1){
if(buttonPressed == false){
buttonPressed = true;
digitToModify++;
if(digitToModify > 4){
digitToModify = 0;
}
}
}
// check for a right button press
else if(digitalRead(rightButton) == 1){
if(buttonPressed == false){
buttonPressed = true;
digitToModify--;
if(digitToModify < 0){
digitToModify = 4;
}
}
}
else{
buttonPressed = false;
}
}
ISR(PCINT2_vect) {
unsigned char result = r.process();
if (result == DIR_NONE) {
// do nothing
}
else if (result == DIR_CW) {
countUp = true;
}
else if (result == DIR_CCW) {
countDown = true;
}
}
The section of code to focus on is with incrementing and decrementing the frequency variable:
void updateFrequency(){
if(countUp == true){
countUp = false;
if(frequency + pow(10, digitToModify) <= 99999) frequency = frequency + pow(10, digitToModify);
}
else if(countDown == true){
countDown = false;
if(frequency - pow(10, digitToModify) > 0) frequency = frequency - pow(10, digitToModify);
}
}
When the rotary encoder is rotated, an interrupt is triggered causing the countUp or countDown boolean flag to be set. When counting up it first checks that we will not exceed 99999 if we were to increment the particular digit we have selected. If it will not exceed this value - it will count this digit up by one.
This code works perfectly fine except for the 'ten thousand' digit. If this digit is currently a '0' or a '1' and then we count up - it will not only increment the 'ten thousand' digit by one - it will also decrement the 'ones digit' by one.
I can fix the code by doing the following:
void updateFrequency(){
if(countUp == true){
countUp = false;
if(frequency + pow(10, digitToModify) <= 99999){
if(digitToModify == 0){
frequency = frequency + 1;
}
else if(digitToModify == 1){
frequency = frequency + 10;
}
else if(digitToModify == 2){
frequency = frequency + 100;
}
else if(digitToModify == 3){
frequency = frequency + 1000;
}
else if(digitToModify == 4){
frequency = frequency + 10000;
}
}
}
else if(countDown == true){
countDown = false;
if(frequency - pow(10, digitToModify) > 0) frequency = frequency - pow(10, digitToModify);
}
}
Here is a youtube clip showing the prototype in operation:
Can anyone provide some insight as to why the 'ones' column would be decrementing?
