Hi Arduino experts
I have a really tricky problem that I am totally stumped on.
My code writes a PWM value to a motor H-Bridge. It then reads an I2C encoder position. (using this AS5600 Library: GitHub - kanestoboi/AS5600: An Arduino library for the AS5600 magnetic encoder)
Trouble is, the encoder randomly locks up, when the analogWrite is used.
The final product rotates a table (like a lazy Susan) to a position then stops.
This cut-down version doesn't do any of that - it's just to demonstrate how low-level the problem is.
Note that in this demo version, there is no motor or H-Bridge attached - the problem is not motor noise, as there is no motor (or H-Bridge), just the internal PWM generation!
#include <AS5600.h>
//Outputs
#define MOTOR 8
#define LED_PIN 13 //Onboard LED
#define DIAG_PIN 15
AS5600 encoder;
int measuredEncoderPosition = 0;
byte ticks = 0;
void setup()
{
//Outputs
pinMode(LED_PIN, OUTPUT); //on arduino board
pinMode(MOTOR, OUTPUT);
Serial1.begin(19200);
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0;
TIMSK1 = (1 << TOIE1); // enable Timer1 overflow interrupt:
TCCR1B |= (1 << CS10); // Set CS10 bit so timer runs at clock speed:
sei(); // enable global interrupts:
}//end Setup
//------------------------------------------------------------------------------------------
void loop()
{
Serial1.println("1");
analogWrite(MOTOR, 100); //run the motor
Serial1.println("2");
measuredEncoderPosition = encoder.getPosition(); // get the absolute position of the encoder
Serial1.println("3");
Serial1.println(measuredEncoderPosition);
Serial1.println("4");
}//end Loop
//-----------------------------------------------------------
ISR(TIMER1_OVF_vect)
{
ticks++;
if (ticks == 100)
{
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
ticks = 0;
}
}
//-----------------------------------------------------------
With the analogWrite disabled:
The encoder will report it's position each time through the loop
The DIAG_PIN toggles to show a square wave on a scope
The LED_PIN toggles once per second on a timer interrupt.
This will run forever, no worries at all.
With the analogWrite enabled:
The encoder will randomly lock up at some time - a few seconds or a few minutes later.
When it locks up, the last thing printed is always Serial1.println("2") - which makes me think that the I2C comms read of the encoder has failed.
The DIAG_PIN stops toggling, and stays flat. (so it can't be looping any more?)
The LED_PIN continues to toggle once per second on a timer interrupt, showing that the CPU is still alive.
Why would the analogWrite upset the I2C communication? I just don't understand, and it's doing my head in.
Things I have tried:
Different encoders, in case it was faulty
Using a different encoder library (the seeed Grove one)
Different Arduino, in case it was faulty
Moving analogWrite to the setup section (so it doesn't re-write each time thru the loop)
Removing the ISR blinky light (no change)
Different comms baud rate.
I find it hard to believe that a modern powerful micro can't do two basic things at the same time.
Something funny is going on, but I can't figure it out.
I would love to receive your expert advice.
Thanks
Pete