Convert TM1637 to TFT Display

I found a sketch that sends bpm from midi clock to a TM1637 Display GitHub,
I'm attempting to send that bpm data to a TFT Display instead,
but I get random symbols on the TFT Display instead of numbers,
can anyone see what I'm doing wrong?

#include <TimerOne.h>

/*
   For all features: if you do not define the pin, the feature will be disabled!
*/

/*
   FEATURE: TAP BPM INPUT
*/
#define TAP_PIN 2
#define TAP_PIN_POLARITY RISING

#define MINIMUM_TAPS 3
#define EXIT_MARGIN 150 // If no tap after 150% of last tap interval -> measure and set

/*
   FEATURE: DIMMER BPM INPUT
*/
// #define DIMMER_INPUT_PIN A0

//#define DIMMER_CHANGE_MARGIN 20 // Big value to make sure this doesn't interfere. Tweak as needed.

/*
   FEATURE: DIMMER BPM INCREASE/DECREASE
*/
//#define DIMMER_CHANGE_PIN A1
//#define DEAD_ZONE 50
//#define CHANGE_THRESHOLD 5000
//#define RATE_DIVISOR 30

/*
   FEATURE: BLINK TEMPO LED
*/
#define BLINK_OUTPUT_PIN 3
#define BLINK_PIN_POLARITY 0  // 0 = POSITIVE, 255 - NEGATIVE
#define BLINK_TIME 4 // How long to keep LED lit in CLOCK counts (so range is [0,24])

/*
   FEATURE: SYNC PULSE OUTPUT
*/
//#define SYNC_OUTPUT_PIN 4 // Can be used to drive sync analog sequencer (Korg Monotribe etc ...)
//#define SYNC_PIN_POLARITY 0 // 0 = POSITIVE, 255 - NEGATIVE

/*
   FEATURE: Send MIDI start/stop
*/
#define START_STOP_INPUT_PIN 4
#define START_STOP_PIN_POLARITY 0 // 0 = POSITIVE, 1024 = NEGATIVE

#define MIDI_START 0xFA
#define MIDI_STOP 0xFC

#define DEBOUNCE_INTERVAL 500L // Milliseconds

/*
   FEATURE: EEPROM BPM storage
*/
#define EEPROM_ADDRESS 0 // Where to save BPM
#ifdef EEPROM_ADDRESS
#include <EEPROM.h>
#endif

/*
   FEATURE: MIDI forwarding
*/
#define MIDI_FORWARD

/*
   FEATURE: TFT display BPM output
*/
#define TFT_DISPLAY
#ifdef TFT_DISPLAY
#include <TFT.h>
#define lcd_cs 10
#define dc     9
#define rst    8
// create an instance of the library
TFT TFTscreen = TFT(lcd_cs, dc, rst);
#endif

/*
   GENERAL PARAMETERS
*/
#define MIDI_TIMING_CLOCK 0xF8
#define CLOCKS_PER_BEAT 24
#define MINIMUM_BPM 400 // Used for debouncing
#define MAXIMUM_BPM 3000 // Used for debouncing

long intervalMicroSeconds;
int bpm;  // BPM in tenths of a BPM!!

boolean initialized = false;
long minimumTapInterval = 60L * 1000 * 1000 * 10 / MAXIMUM_BPM;
long maximumTapInterval = 60L * 1000 * 1000 * 10 / MINIMUM_BPM;

volatile long firstTapTime = 0;
volatile long lastTapTime = 0;
volatile long timesTapped = 0;

volatile int blinkCount = 0;

int lastDimmerValue = 0;

boolean playing = false;
long lastStartStopTime = 0;

//#ifdef TM1637_DISPLAY
//TM1637Display display(TM1637_CLK_PIN, TM1637_DIO_PIN);
uint8_t tft_data[4] = {0x00, 0x00, 0x00, 0x00};
//#endif

#ifdef DIMMER_CHANGE_PIN
long changeValue = 0;
#endif

void setup() {
  //  Set MIDI baud rate:
  //Serial.begin(31250);
  Serial.begin(31250);

  TFTscreen.begin();
  TFTscreen.background(0, 0, 0);
  TFTscreen.setRotation(1);

  TFTscreen.setTextSize(2);
  TFTscreen.stroke(255, 255, 255);

  // Set pin modes
#ifdef BLINK_OUTPUT_PIN
  pinMode(BLINK_OUTPUT_PIN, OUTPUT);
#endif
#ifdef SYNC_OUTPUT_PIN
  pinMode(SYNC_OUTPUT_PIN, OUTPUT);
#endif
#ifdef DIMMER_INPUT_PIN
  pinMode(DIMMER_INPUT_PIN, INPUT);
#endif
#ifdef START_STOP_INPUT_PIN
  pinMode(START_STOP_INPUT_PIN, INPUT);
#endif

#ifdef EEPROM_ADDRESS
  // Get the saved BPM value from 2 stored bytes: MSB LSB
  bpm = EEPROM.read(EEPROM_ADDRESS) << 8;
  bpm += EEPROM.read(EEPROM_ADDRESS + 1);
  if (bpm < MINIMUM_BPM || bpm > MAXIMUM_BPM) {
    bpm = 1200;
  }
#endif

#ifdef TAP_PIN
  // Interrupt for catching tap events
  attachInterrupt(digitalPinToInterrupt(TAP_PIN), tapInput, TAP_PIN_POLARITY);
#endif

  // Attach the interrupt to send the MIDI clock and start the timer
  Timer1.initialize(intervalMicroSeconds);
  Timer1.setPeriod(calculateIntervalMicroSecs(bpm));
  Timer1.attachInterrupt(sendClockPulse);

#ifdef DIMMER_INPUT_PIN
  // Initialize dimmer value
  lastDimmerValue = analogRead(DIMMER_INPUT_PIN);
#endif

#ifdef TM1637_DISPLAY
  display.setBrightness(TM1637_BRIGHTNESS);
  setDisplayValue(bpm);
#endif
}

void loop() {
  long now = micros();

#ifdef TAP_PIN
  /*
     Handle tapping of the tap tempo button
  */
  if (timesTapped > 0 && timesTapped < MINIMUM_TAPS && (now - lastTapTime) > maximumTapInterval) {
    // Single taps, not enough to calculate a BPM -> ignore!
    timesTapped = 0;
  } else if (timesTapped >= MINIMUM_TAPS) {
    long avgTapInterval = (lastTapTime - firstTapTime) / (timesTapped - 1);
    if ((now - lastTapTime) > (avgTapInterval * EXIT_MARGIN / 100)) {
      bpm = 60L * 1000 * 1000 * 10 / avgTapInterval;
      updateBpm(now);

      // Update blinkCount to make sure LED blink matches tapped beat
      blinkCount = ((now - lastTapTime) * 24 / avgTapInterval) % CLOCKS_PER_BEAT;

      timesTapped = 0;
    }
  }
#endif

#ifdef DIMMER_INPUT_PIN
  /*
     Handle change of the dimmer input
  */
  int curDimValue = analogRead(DIMMER_INPUT_PIN);
  if (curDimValue > lastDimmerValue + DIMMER_CHANGE_MARGIN
      || curDimValue < lastDimmerValue - DIMMER_CHANGE_MARGIN) {
    // We've got movement!!
    bpm = map(curDimValue, 0, 1024, MINIMUM_BPM, MAXIMUM_BPM);

    updateBpm(now);
    lastDimmerValue = curDimValue;
  }
#endif

#ifdef DIMMER_CHANGE_PIN
  int curDimValue = analogRead(DIMMER_CHANGE_PIN);
  if (bpm > MINIMUM_BPM && curDimValue < (512 - DEAD_ZONE)) {
    int val = (512 - DEAD_ZONE - curDimValue) / RATE_DIVISOR;
    changeValue += val * val;
  } else if (bpm < MAXIMUM_BPM && curDimValue > (512 + DEAD_ZONE)) {
    int val = (curDimValue - 512 - DEAD_ZONE) / RATE_DIVISOR;
    changeValue += val * val;
  } else {
    changeValue = 0;
  }
  if (changeValue > CHANGE_THRESHOLD) {
    bpm += curDimValue < 512 ? -1 : 1;
    updateBpm(now);
    changeValue = 0;
  }
#endif

#ifdef START_STOP_INPUT_PIN
  /*
     Check for start/stop button pressed
  */
  boolean startStopPressed = (START_STOP_PIN_POLARITY - digitalRead(START_STOP_INPUT_PIN)) == HIGH;
  if (startStopPressed && (lastStartStopTime + (DEBOUNCE_INTERVAL * 1000)) < now) {
    startOrStop();
    lastStartStopTime = now;
  }
#endif

#ifdef MIDI_FORWARD
  /*
     Forward received serial data
  */
  while (Serial.available()) {
    int b = Serial.read();
    Serial.write(b);
  }
#endif
}

void tapInput() {
  long now = micros();
  if (now - lastTapTime < minimumTapInterval) {
    return; // Debounce
  }

  if (timesTapped == 0) {
    firstTapTime = now;
  }

  timesTapped++;
  lastTapTime = now;
}

void startOrStop() {
  if (!playing) {
    Serial.write(MIDI_START);
  } else {
    Serial.write(MIDI_STOP);
  }
  playing = !playing;
}

void sendClockPulse() {
  // Write the timing clock byte
  Serial.write(MIDI_TIMING_CLOCK);

  blinkCount = (blinkCount + 1) % CLOCKS_PER_BEAT;
  if (blinkCount == 0) {
    // Turn led on
#ifdef BLINK_OUTPUT_PIN
    analogWrite(BLINK_OUTPUT_PIN, 255 - BLINK_PIN_POLARITY);
#endif

#ifdef SYNC_OUTPUT_PIN
    // Set sync pin to HIGH
    analogWrite(SYNC_OUTPUT_PIN, 255 - SYNC_PIN_POLARITY);
#endif
  } else {
#ifdef SYNC_OUTPUT_PIN
    if (blinkCount == 1) {
      // Set sync pin to LOW
      analogWrite(SYNC_OUTPUT_PIN, 0 + SYNC_PIN_POLARITY);
    }
#endif
#ifdef BLINK_OUTPUT_PIN
    if (blinkCount == BLINK_TIME) {
      // Turn led on
      analogWrite(BLINK_OUTPUT_PIN, 0 + BLINK_PIN_POLARITY);
    }
#endif
  }
}

void updateBpm(long now) {
  // Update the timer
  long interval = calculateIntervalMicroSecs(bpm);
  Timer1.setPeriod(interval);

#ifdef EEPROM_ADDRESS
  // Save the BPM in 2 bytes, MSB LSB
  EEPROM.write(EEPROM_ADDRESS, bpm / 256);
  EEPROM.write(EEPROM_ADDRESS + 1, bpm % 256);
#endif

#ifdef TFT_DISPLAY
  setDisplayValue(bpm);
#endif
}

long calculateIntervalMicroSecs(int bpm) {
  // Take care about overflows!
  return 60L * 1000 * 1000 * 10 / bpm / CLOCKS_PER_BEAT;
}

#ifdef TFT_DISPLAY
void setDisplayValue(int value) {
  //  tft_data[0] = value >= 1000 ? display.encodeDigit(value / 1000) : 0x00;
  //  tft_data[1] = value >= 100 ? display.encodeDigit((value / 100) % 10) : 0x00;
  //  tft_data[2] = value >= 10 ? display.encodeDigit((value / 10) % 10) : 0x00;
  //  tft_data[3] = display.encodeDigit(value % 10);
  //delete old number
  TFTscreen.background(0, 0, 0);
  //print new text
  TFTscreen.text(bpm, 15, 50);

}
#endif

text() is expecting a string (aka char array) as the first parameter, not aninteger. YOU need to convert bpm into the string before passing it in

char text[10];
itoa(bmp, text, 10);
TFTscreen.text(text,15,50);
1 Like

works great thank you!

A bpm of 120.5 is displayed as 1205

is there a way to add the decimal point?

dtostrf() - google is your friend for details...

Awesome thank you

This almost works, but a bpm of 90.0 is displayed as 900.0

  char text[10];
  itoa(bpm, text, 10);
  float bpmtft = bpm;
  //static char text[4];
  dtostrf(bpmtft, 4, 1, text);
  TFTscreen.text(text, 15, 50);

Is a BPM of 90 represented inside the code as 900?

  char text[10];
  dtostrf(bpm/10.0, 4, 1, text);
  TFTscreen.text(text, 15, 50);
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.