Combine two code midi cv generator

Hello, i just built this cool arduino midi clock generator by ymnk successfully ,yayy

Then i stumbled this cool analog scrolling graph by dogukan-bicer and success too

I wanna combine both since the scrolling graph is just use one potentiometer on same input (A0)

I tried to :
1.Copy paste scrolling graph into clockbox and vice versa into one file
2. Rename void and void loop also void setup when error appear, and it can compile and uploaded. But the oled is blank , lul. While the clockbox is still functioning , working blinking led bpm

Please help me, im under water
Lol

And this is my demo, while oled is blank but clockbox is okey :

Mutant fm synth by meebleeps
Drumkid by Matt bradsaw
Clockbox by ymnk

3 Likes

you can only have one

void setup ()

This runs once and once only ever

void loop ()

is the master loop

You probably need to combnie the contents of both setup voids in one

and then rename the other two other loops for each function

say

void clock()
void graph()

and then in void loop have the void loop call each function.

void loop () {
clock();
graph();
}

That’s all just an assumption mind, but just copying and pasting two togheter is not going to work.

Rob

1 Like

There is also the possibility that they cant work together on a single arduino. Depending on protocol, serial usage, etc… maybe it is not possible.

agree, but if it’s not flagging any errors it sound like there’s no library mismatches and so long as there is no crossover on pin or variable useage, then the two could potentaily co-exist although there may be timing issues etc…

not looked at either code so far myself.

1 Like

Yo thank you my man. I follow ur suggestion, it can compile but both code doesnt function, oled screen still blank, and start button doesnt trigger led bpm. And i also put second pot for graph scrolling, so its input from A2

Is this right?

#include <uClock.h>

#include <Wire.h>
#include <SPI.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define ANALOG_SYNC_RATIO 4
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 _display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const int ANALOG_INPUT_PIN = A2;
const int MIN_ANALOG_INPUT = 0;
const int MAX_ANALOG_INPUT = 1023;
const int DELAY_LOOP_MS = 5; // change to slow down how often to read and graph value

int _circularBuffer[SCREEN_WIDTH]; //fast way to store values
int _curWriteIndex = 0; // tracks where we are in the circular buffer

// for tracking fps
float _fps = 0;
unsigned long _frameCount = 0;
unsigned long _fpsStartTimeStamp = 0;

// status bar
boolean _drawStatusBar = true; // change to show/hide status bar
int _graphHeight = SCREEN_HEIGHT;
bool screen_overflow=false;

bool currentState = false;
bool currentSwitchState = false;
bool needsToSendMidiStart = false;

const byte pinCount = 4;
byte digitalPinOut[pinCount] = {3,5,7,9}; //Define analog clock outputs here

void clockOutput96PPQN(uint32_t* tick) {
if (needsToSendMidiStart) {
needsToSendMidiStart = false;
Serial.write(0xFA);
}
Serial.write(0xF8);
}

void clockOutput32PPQN(uint32_t* tick) {
if (currentState) {
if ((*tick % ANALOG_SYNC_RATIO ) == 0) {
sendDigitalOut(true);
} else {
sendDigitalOut(false);
}
}
}

void sendDigitalOut(bool state) {
byte pinState = state ? HIGH : LOW;

for (byte i = 0; i < pinCount; i++) {
digitalWrite(digitalPinOut[i], pinState);
}
}

void setup() {
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
_display.begin(SSD1306_SWITCHCAPVCC, 0x3C);// Address 0x3D for 128x64
_display.setTextSize(1);
_display.setTextColor(WHITE, BLACK);
_display.setCursor(0, 0);
_display.clearDisplay();
_graphHeight = SCREEN_HEIGHT - 10;
_fpsStartTimeStamp = millis();

Serial.begin(31250);
uClock.init();

pinMode(2, INPUT);

for (byte i = 0; i < pinCount; i++) {
pinMode(digitalPinOut[i], OUTPUT);
}

uClock.init();

uClock.setClock96PPQNOutput(clockOutput96PPQN);
uClock.setClock32PPQNOutput(clockOutput32PPQN);
uClock.setTempo(96);

uClock.start();
}

void toggleStartStop() {
if (currentState) {
Serial.write(0xFC);
sendDigitalOut(false);
currentState = false;

} else {
uClock.stop();
delay(20);
currentState = true;
needsToSendMidiStart = true;
uClock.start();
}
}

void loop() {
clockbox();
graph();
}
void graph() {
// Clear the display on each frame. We draw from the _circularBuffer
_display.clearDisplay();

// Read and store the analog data into a circular buffer
int analogVal = analogRead(ANALOG_INPUT_PIN);
_circularBuffer[_curWriteIndex++] = analogVal;

// Set the circular buffer index back to zero when it reaches the
// right of the screen
if(_curWriteIndex >= 128){
_curWriteIndex = 0;
}
drawStatusBar(analogVal);
// Draw the line graph based on data in _circularBuffer
int xPos = 0;

if(screen_overflow==true){
for (int i = _curWriteIndex; i < _display.width(); i++){
int analogVal = _circularBuffer[i];
drawLine(xPos, analogVal);
xPos++;
}

for(int i = 0; i < _curWriteIndex; i++){
int analogVal = _circularBuffer[i];
drawLine(xPos, analogVal);
xPos++;
}
}else if(screen_overflow==false){
for(int i = 0; i < _curWriteIndex; i++){
int analogVal = _circularBuffer[i];
drawLine(xPos, analogVal);
xPos++;
}
if(xPos==127)
{
screen_overflow=true;
}
}
_display.display();
calcFrameRate();
delay(DELAY_LOOP_MS);
}

void clockbox() {
int tempoPot = analogRead(A0);

float tempo = ((float)tempoPot/1024.f)*210.f + 30.f;

uClock.setTempo(tempo);
int switchState = digitalRead(2);

if ((switchState == HIGH) && !currentSwitchState) {
toggleStartStop();
currentSwitchState = true;
}

if (switchState == LOW) {
currentSwitchState = false;
}

delay(30);
}

void drawLine(int xPos, int analogVal){
int lineHeight = map(analogVal, MIN_ANALOG_INPUT, MAX_ANALOG_INPUT, 0, _graphHeight);
int yPos = _display.height() - lineHeight;
_display.drawFastVLine(xPos, yPos, lineHeight, SSD1306_WHITE);
}

/**

  • Call this every frame to calculate frame rate
    */
    void calcFrameRate() {

unsigned long elapsedTime = millis() - _fpsStartTimeStamp;
_frameCount++;
if (elapsedTime > 1000) {
_fps = _frameCount / (elapsedTime / 1000.0);
_fpsStartTimeStamp = millis();
_frameCount = 0;
}
}

/**

  • Draws the status bar at top of screen with fps and analog value
    */
    void drawStatusBar(int analogVal) {

    // erase status bar by drawing all black
    _display.fillRect(0, 0, _display.width(), 8, SSD1306_BLACK);

// Draw current val
_display.setCursor(0, 0);
_display.print(analogVal);

// Draw frame count
int16_t x1, y1;
uint16_t w, h;
_display.getTextBounds(“XX.XX fps”, 0, 0, &x1, &y1, &w, &h);
_display.setCursor(_display.width() - w, 0);
_display.print(_fps);
_display.print(" fps");
}

Hmmm, so if i buy second arduino, put separate code each,
Then put dual potentiometer ,both middle pin on A0
that may work?

you need to start debugging.

in the main void loop add a statement to print tomething to the serial monitor in the Arduio IDE

void loop() {
Serial.println(“Calling Clock Routine”);
clockbox();
Serial.println(“Calling Graph Routine”);
graph();
}

in each routine void loop add something like a

Serial.println(“CLOCK ROUTINE”);

and monitor the serial monitor in the IDE, to see if the routines are being called and running. if it’s going by too fast on the serial monitor, add in a delay , it may make things generlay functiuon badly but you will see the flow

delay(1000);

Rob

I make void loop like this

void loop () {
Serial.println (“CALLING CLOCK ROUTINE”);
clockbox();
Serial.println(“CALLING GRAPH ROUTINE”);
graph();
delay(1000);
}

then enter serial monitor menu
And i just see square square square lol
What is this hahaha

Change the baud rate in the serial monitor, default should be 9600.

Or change the default baud rate in the code by
Serial.begin(115000);
And select the same value in the monitor.

this is in void setup

Serial.begin(31250);

is the serial line being used for something?? if not just change that to 9600 or your monitor to 31250

I change the baud rate on serial and it looks like this
Haha

The baud rate in the serial.begin statement and the terminal (bottom right) MUST be the same. It is normal to get some garbage when the arduino starts up, but after that the text should be readable. E.g. choose 115200 in the terminal window and the serial.begin(115200) and you should be seeing things (provided you are printing stuff to the serial port, of course).
Also if you post some code, then use the 'preformatted text mode (this adds 3 '-characters at the beginning and end of the code segment) so that the indentation of the code will be preserved. That makes it much easier to identify blocks of code and read the code in general.
So stead of:

for(int i = 0; i < _curWriteIndex; i++){
int analogVal = _circularBuffer[i];
drawLine(xPos, analogVal);
xPos++;
}

you will then see

for(int i = 0; i < _curWriteIndex; i++) {
  int analogVal = _circularBuffer[i];
  drawLine(xPos, analogVal);
  xPos++;
}

In its present format it will cost quite a lot of effort for anyone to find any irregulaties in your code. So this will not invite a lot of people to have a look.
Maybe post the code again and tell us how far you got it working?

I have found this quite common when using serial monitor and an Arduino, not found a way around it yet, but it does make debugging a pain,

In what way do you find it a problem?

the only time I have had a real problem was when a Nano had an incorrect clock speed compared to the hardware board definition.

Rob

I’ve just never got a nano to send successfully to serial, no problems with Teensy and others, just for me no go with Nano, maybe it’s something to do with the serial port being shared, I know on the last project I had to switch out the midi to do uploads successfuly.

I change serial begin code to 115200 , and monitor too
And this is what it looks like

It keeps calling

Just for a test, can you set your display to 128x32 to see if it initializes

Please change the post so that it is posted as preformatted text (option next to quotes in the input box). Oh, and in stead of ms word use notepad (which keeps the program code unchanged).

type or paste code here
```#include <uClock.h>

#include <Wire.h>
#include <SPI.h>

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define ANALOG_SYNC_RATIO 4
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 _display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const int ANALOG_INPUT_PIN = A2;
const int MIN_ANALOG_INPUT = 0;
const int MAX_ANALOG_INPUT = 1023;
const int DELAY_LOOP_MS = 5; // change to slow down how often to read and graph value

int _circularBuffer[SCREEN_WIDTH]; //fast way to store values
int _curWriteIndex = 0; // tracks where we are in the circular buffer

// for tracking fps
float _fps = 0;
unsigned long _frameCount = 0;
unsigned long _fpsStartTimeStamp = 0;

// status bar
boolean _drawStatusBar = true; // change to show/hide status bar
int _graphHeight = SCREEN_HEIGHT;
bool screen_overflow = false;

bool currentState = false;
bool currentSwitchState = false;
bool needsToSendMidiStart = false;

const byte pinCount = 4;
byte digitalPinOut[pinCount] = {3, 5, 7, 9}; //Define analog clock outputs here

void clockOutput96PPQN(uint32_t* tick) {
  if (needsToSendMidiStart) {
    needsToSendMidiStart = false;
    Serial.write(0xFA);
  }
  Serial.write(0xF8);
}

void clockOutput32PPQN(uint32_t* tick) {
  if (currentState) {
    if ((*tick % ANALOG_SYNC_RATIO ) == 0) {
      sendDigitalOut(true);
    } else {
      sendDigitalOut(false);
    }
  }
}

void sendDigitalOut(bool state) {
  byte pinState = state ? HIGH : LOW;

  for (byte i = 0; i < pinCount; i++) {
    digitalWrite(digitalPinOut[i], pinState);
  }
}

void setup() {
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  _display.begin(SSD1306_SWITCHCAPVCC, 0x3C);// Address 0x3D for 128x64
  _display.setTextSize(1);
  _display.setTextColor(WHITE, BLACK);
  _display.setCursor(0, 0);
  _display.clearDisplay();
  _graphHeight = SCREEN_HEIGHT - 10;
  _fpsStartTimeStamp = millis();

  Serial.begin(115200);
  uClock.init();

  pinMode(2, INPUT);

  for (byte i = 0; i < pinCount; i++) {
    pinMode(digitalPinOut[i], OUTPUT);
  }

  uClock.init();

  uClock.setClock96PPQNOutput(clockOutput96PPQN);
  uClock.setClock32PPQNOutput(clockOutput32PPQN);
  uClock.setTempo(96);

  uClock.start();
}

void toggleStartStop() {
  if (currentState) {
    Serial.write(0xFC);
    sendDigitalOut(false);
    currentState = false;

  } else {
    uClock.stop();
    delay(20);
    currentState = true;
    needsToSendMidiStart = true;
    uClock.start();
  }
}

void loop() {
  Serial.println("Calling clockbox Routine");
  clockbox();
  Serial.println("Calling graph Routine");
  graph();
  delay(1000);
}

void graph() {
  // Clear the display on each frame. We draw from the _circularBuffer
  _display.clearDisplay();

  // Read and store the analog data into a circular buffer
  int analogVal = analogRead(ANALOG_INPUT_PIN);
  _circularBuffer[_curWriteIndex++] = analogVal;

  // Set the circular buffer index back to zero when it reaches the
  // right of the screen
  if (_curWriteIndex >= 128) {
    _curWriteIndex = 0;
  }
  drawStatusBar(analogVal);
  // Draw the line graph based on data in _circularBuffer
  int xPos = 0;

  if (screen_overflow == true) {
    for (int i = _curWriteIndex; i < _display.width(); i++) {
      int analogVal = _circularBuffer[i];
      drawLine(xPos, analogVal);
      xPos++;
    }

    for (int i = 0; i < _curWriteIndex; i++) {
      int analogVal = _circularBuffer[i];
      drawLine(xPos, analogVal);
      xPos++;
    }
  } else if (screen_overflow == false) {
    for (int i = 0; i < _curWriteIndex; i++) {
      int analogVal = _circularBuffer[i];
      drawLine(xPos, analogVal);
      xPos++;
    }
    if (xPos == 127)
    {
      screen_overflow = true;
    }
  }
  _display.display();
  calcFrameRate();
  delay(DELAY_LOOP_MS);
}

void clockbox() {
  int tempoPot = analogRead(A0);

  float tempo = ((float)tempoPot / 1024.f) * 210.f + 30.f;

  uClock.setTempo(tempo);
  int switchState = digitalRead(2);

  if ((switchState == HIGH) && !currentSwitchState) {
    toggleStartStop();
    currentSwitchState = true;
  }

  if (switchState == LOW) {
    currentSwitchState = false;
  }

  delay(30);
}

void drawLine(int xPos, int analogVal) {
  int lineHeight = map(analogVal, MIN_ANALOG_INPUT, MAX_ANALOG_INPUT, 0, _graphHeight);
  int yPos = _display.height() - lineHeight;
  _display.drawFastVLine(xPos, yPos, lineHeight, SSD1306_WHITE);
}

/**

  Call this every frame to calculate frame rate
*/
void calcFrameRate() {
  unsigned long elapsedTime = millis() - _fpsStartTimeStamp;
  _frameCount++;
  if (elapsedTime > 1000) {
    _fps = _frameCount / (elapsedTime / 1000.0);
    _fpsStartTimeStamp = millis();
    _frameCount = 0;
  }
}


void drawStatusBar(int analogVal) {

  // erase status bar by drawing all black
  _display.fillRect(0, 0, _display.width(), 8, SSD1306_BLACK);

  // Draw current val
  _display.setCursor(0, 0);
  _display.print(analogVal);

  // Draw frame count
  int16_t x1, y1;
  uint16_t w, h;
  _display.getTextBounds("XX.XX fps", 0, 0, &x1, &y1, &w, &h);
  _display.setCursor(_display.width() - w, 0);
  _display.print(_fps);
  _display.print(" fps");
}

Holyhell it works sirr
Woww
Whats happening?

I set display 128x32, change both clockbox & graph scroll potentiometer to A2, erase the serial print line, delay
Now its perfect
Thank you man
Ure the best

Im demoing :

3 Likes