The problem is that after some unspecified time, hours or days, Nano stops reading messages or triggering output pins. Later, I added the heartbeat library and the LE diode on pin 13 to the code, so that I could visually monitor whether the processor is alive or not. The heartbeat diode continues to beat but the arduino stops responding to MIDI messages. The code was taken from Note and Volts and partially modified.
// ** Requires Arduino MIDI Library v4.2 or later **
#include <MIDI.h>
#include <avr/wdt.h>
#include <HeartbeatLed.h>
//Set NoteOrCC to 'true' for NOTE or 'false' for CC
const bool NoteOrCC = false;
// Set Midi Channel: (1-16 or 0 for OMNI)
#define MIDI_CHANNEL 1
// Set Note/CC ON limit (1-127): Relay will turn ON when Note/CC Velocity/value is greater or equal to this number
#define VALUE_ON 2
// Set Midi Note/CC numbers here (0-127):
#define VALUE1 0
#define VALUE2 1
#define VALUE3 2
#define VALUE4 3
#define VALUE5 124
// Arduino digital pin numbers for relays:
#define RELAY1 2
#define RELAY2 3
#define RELAY3 4
#define RELAY4 5
#define RELAY5 6
// External LED Indicator pin
#define LED_EXTERNAL 10
// Arduino LED pin
#define LED 11
HeartbeatLed heartbeat(13)
const byte MIDI_CHAN = MIDI_CHANNEL;
const byte VALUE1_NUM = VALUE1;
const byte VALUE2_NUM = VALUE2;
const byte VALUE3_NUM = VALUE3;
const byte VALUE4_NUM = VALUE4;
const byte VALUE5_NUM = VALUE5;
MIDI_CREATE_DEFAULT_INSTANCE();
void setup() {
pinMode(LED, OUTPUT);
pinMode(LED_EXTERNAL, OUTPUT);
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
pinMode(RELAY3, OUTPUT);
pinMode(RELAY4, OUTPUT);
pinMode(RELAY5, OUTPUT);
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, LOW);
digitalWrite(RELAY3, LOW);
digitalWrite(RELAY4, LOW);
digitalWrite(RELAY5, LOW);
digitalWrite(LED, HIGH);
digitalWrite(LED_EXTERNAL, HIGH);
if (MIDI_CHAN == 0) MIDI.begin(MIDI_CHANNEL_OMNI);
else MIDI.begin(MIDI_CHAN);
//MIDI.begin();
MIDI.setHandleControlChange(HandleCC);
wdt_enable(WDTO_4S);
wdt_reset();
}
void loop() {
MIDI.read();
blinkLed(false);
wdt_reset();
heartbeat.update();
}
void HandleCC(byte channel, byte number, byte value) {
if (channel == 1) {
if (number == VALUE1_NUM) {
if (value >= VALUE_ON) {
digitalWrite(RELAY1, HIGH); //Turn RELAY ON
} else {
digitalWrite(RELAY1, LOW); //Turn RELAY OFF
}
}
if (number == VALUE2_NUM) {
if (value >= VALUE_ON) {
digitalWrite(RELAY2, HIGH); //Turn RELAY ON
} else {
digitalWrite(RELAY2, LOW); //Turn RELAY OFF
}
}
if (number == VALUE3_NUM) {
if (value >= VALUE_ON) {
digitalWrite(RELAY3, HIGH); //Turn RELAY ON
} else {
digitalWrite(RELAY3, LOW); //Turn RELAY OFF
}
}
if (number == VALUE4_NUM) {
if (value >= VALUE_ON) {
digitalWrite(RELAY4, HIGH); //Turn RELAY ON
} else {
digitalWrite(RELAY4, LOW); //Turn RELAY OFF
}
}
if (number == VALUE5_NUM) {
if (value >= VALUE_ON) {
digitalWrite(RELAY5, HIGH); //Turn RELAY ON
} else {
digitalWrite(RELAY5, LOW); //Turn RELAY OFF
}
}
}
blinkLed(true);
}
void blinkLed(bool trigger) {
static bool busy = false;
static unsigned long previousMillis = 0;
const int ledInterval = 50;
unsigned long currentMillis = millis();
if (trigger == true && busy == false) {
digitalWrite(LED, LOW);
digitalWrite(LED_EXTERNAL, LOW);
previousMillis = currentMillis;
busy = true;
} else {
if (currentMillis - previousMillis >= ledInterval) {
//previousMillis = currentMillis;
digitalWrite(LED, HIGH);
digitalWrite(LED_EXTERNAL, HIGH);
busy = false;
}
}
}
You might be having problems from "millis" overflowing back to zero, so your indicator light doesn't blink. Have you tested if it is just the blinking which is malfunctioning, or it is also not sending midi message?
Thanks for reply, but pin D0 is the rx pin on Arduino nano, second from the corner. Labeled on schematic as 2.
Like I said, everything works fine for a while. Listens to messages, activates relays, works perfectly for days 24/7. Until one moment. Heartbeat diode on pin13 are blinking, but there is no response to MIDI, MIDI flow led on pins 11 and 12 also stop blinking.
Now I unsolder the 1k resistors on the rx, tx lines, between ATmega and ch340. Maybe a problem in ch340....
At first sight, the code looks alright. Are you able to confirm that the MIDI messages are still received and decoded correctly by the 6N138? (E.g. using a second Arduino or USB-to-TTL adapter connected to the same pin.)
Are you using a genuine ATmega chip? I've encountered some problems with a batch of Chinese Nano clones locking up after some time, especially when subjected to EMI from a nearby motor. I'm not saying it's the same issue, but hardware problems or a counterfeit microcontroller could be to blame here as well.
it is a clone. I suspected the same. I saw that a local store has an ATmega 328P-PU take that and a 16MHz crystal and a couple of 22p capacitors. Then build my own Nano
Millis return a "long" data type, representing the time elapsed since the device was powered on. When this value gets to its maximum, it loops back to zero. When that happens, previous will be a large number, and current millis will be a low number. The line currentmillis - previosmillis will give a negative number, and timer no longer works for blinking led
I looked at the signal with an oscilloscope after the optocoupler and it looks great. In an attempt to debug I added a 2 schmith trigger in line as a signal buffer.
I think I found where the error is. The real problem is not ch340 or the code, but a problem in the resonator or in the quartz, which oscillates, in my case at 15.833MHz. So the midi baudrate is 30923KHz and not 31250. Which is very close to the limit of 1% for the Midi standard.
If you add to that clock drift by time and temperature.... it took 24 hours to fall out of sync.
I still have to solve the clock, so I will write here about the results.