Hello,
I have a weird issue with a Nano clone (CH340, not FTDI) and one of these I²C 128x32 OLED, driven with u8g2...
Until now, I've been using some OLEDs, only with STM32s (BluePill and BlackPill, genuine MCUs and chinese clones), without a problem. Today, I needed to quickly make a pulse generator, and a Nano was ideal for this project (thanks to Paul Stoffregen for TimerOne and MsTimer2 libraries that made things as easy as writing an #include !).
But, everytime the nano and its display are powered THROUGHT THE USB PORT, it reboots on and on ! Removing the display, or not initializing u8g2 solves the problem. But I have no display Not really a solution...
I took a ProMini that I had in the drawers, and flashed it using a (genuine) Arduino FTDI adapter, and no problem. No reboots.
I think the problem is hardware related : is there a known issue with CH340 Nanos and I²C ?
Not a huge issue for me, as the circuit is powered by an external PSU ; but I'd like to know !
The code is pretty simple and straightforward (who said quick and dirty ??? I can hear you !):
[EDIT]
It seems I found a problem in the code while editing this message. Will update in a few moments !
(there were errors in the comments)
/*
RPM generator
*/
#include <MsTimer2.h>
#include <ClickEncoder.h>
#include <TimerOne.h>
#include <Wire.h>
#include <SPI.h>
#include <U8x8lib.h>
#include <U8g2lib.h>
//#define __SERIAL_DEBUG
#define ENC_A 4
#define ENC_B 3
#define ENC_BTN 2
#define OUT_PIN 9
/*
SCK A5
SDA A6
*/
#define TIMER1_SIGNAL_PERIOD 1000 // 1000 microseconds
#define TIMER2_ENCODER_PERIOD 1 // 1 millisecond
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C oled(U8G2_R0); // full buffer
ClickEncoder encoder(ENC_A, ENC_B, ENC_BTN);
void encoderIsr()
{
encoder.service();
}
void setup(void)
{
#ifdef __SERIAL_DEBUG
Serial.begin(115200);
Serial.println("Hello !");
#endif
pinMode(LED_BUILTIN, OUTPUT);
// encoder
pinMode(ENC_BTN, INPUT_PULLUP);
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
encoder.setDoubleClickEnabled(false);
encoder.setButtonHeldEnabled(false);
encoder.setAccelerationEnabled(false);
// encoder timer
MsTimer2::set(TIMER2_ENCODER_PERIOD, encoderIsr); // 1 millisecond
MsTimer2::start();
// output
pinMode(OUT_PIN, OUTPUT);
Timer1.setPeriod(TIMER1_SIGNAL_PERIOD); // 1000 microseconds
Timer1.pwm(OUT_PIN, 100);
Timer1.initialize(4); // 40 us = 25 kHz
// display
oled.begin();
oled.setContrast(1);
oled.setFont(u8g2_font_6x10_tf);
oled.clear();
delay(1000);
}
uint32_t rpm = 0;
uint32_t rpmOld = -1;
int16_t encPos = 0;
int16_t encPosOld = -1;
void loop(void)
{
uint8_t buttonState = encoder.getButton();
#ifdef __SERIAL_DEBUG
if (buttonState != 0)
Serial.println(buttonState);
#endif
if (buttonState != 0 && buttonState == ClickEncoder::Clicked)
rpm = 1500;
encPos += encoder.getValue();
int16_t delta = encPos - encPosOld;
encPosOld = encPos;
if (delta > 0 && rpm < 500000)
{
if (rpm >= 100000)
rpm += 10000;
else if (rpm >= 50000)
rpm += 5000;
else if (rpm >= 10000)
rpm += 1000;
else if (rpm >= 5000)
rpm += 500;
else if (rpm >= 1000)
rpm += 100;
else if (rpm >= 500)
rpm += 50;
else if (rpm >= 100)
rpm += 10;
else if (rpm >= 50)
rpm += 5;
else
rpm += 1;
}
if (delta < 0 && rpm > 0)
{
// EDITED BEGIN
/*
if (encPos == 0)
rpm = 0;
else
*/
// EDITED END
if (rpm <= 10)
rpm -= 1;
else if (rpm <= 50)
rpm -= 1;
else if (rpm <= 100)
rpm -= 5;
else if (rpm <= 500)
rpm -= 10;
else if (rpm <= 1000)
rpm -= 50;
else if (rpm <= 5000)
rpm -= 100;
else if (rpm <= 10000)
rpm -= 500;
else if (rpm <= 50000)
rpm -= 1000;
else if (rpm <= 100000)
rpm -= 5000;
else
rpm -= 10000;
}
if (rpm != rpmOld)
{
if (rpm != 0)
{
float period = 1000000.0 / (rpm / 60.0); // micros
float Hz = 1.0 / ((float)period / 1000000.0);
Timer1.setPeriod(period); // micros
Timer1.pwm(OUT_PIN, 100);
#ifdef __SERIAL_DEBUG
Serial.print(encPos); Serial.print(" ");
Serial.print("RPM = "); Serial.print(rpm);
Serial.print(" / Period = "); Serial.print((float)period/1000.0);
Serial.print(" ms / Freq. = "); Serial.print(Hz);
Serial.println(" Hz");
#endif
char line0[64] = "";
String strHz(Hz);
sprintf(line0, "%lu RPM %s Hz", rpm, strHz.c_str());
char line1[64] = "";
String strPeriod((float)period/1000);
sprintf(line1, "%s ms", strPeriod.c_str());
u8g2_uint_t x0 = (128 - oled.getStrWidth(line0)) >> 1;
u8g2_uint_t x1 = (128 - oled.getStrWidth(line1)) >> 1;
oled.clearBuffer();
oled.drawStr(x0, 10, line0);
oled.drawStr(x1, 30, line1);
oled.sendBuffer();
}
else
{
digitalWrite(OUT_PIN, LOW);
#ifdef __SERIAL_DEBUG
Serial.print("RPM = "); Serial.print(rpm);
Serial.print(" Period = "); Serial.print("N/A");
Serial.print(" Freq. = "); Serial.println(0);
#endif
char line0[64] = "";
sprintf(line0, "%lu RPM 0.00 Hz", rpm);
oled.clearBuffer();
oled.setFont(u8g2_font_6x10_tf);
oled.drawStr((128 - oled.getStrWidth(line0)) >> 1, 10, line0);
oled.sendBuffer();
}
rpmOld = rpm;
}
}
Attachment = working electronics ; with a USB cable, it reboots on and on...