Very odd issues with a custom microcontroller and RC receiver libraries

...forum looks different from my last visit.

Anyways, this is a question about a particular bit of code that won't work properly on my custom microcontroller board. The board has an atmega328-au connected to two a4950 motor drivers, a servo input, and a 12V connection. That's it. It doesn't even have an external oscillator.

The input pins of the a4950s are on the atmega's PD5 and PD6, and PB1 and PB2. This is equivalent to D5, D6, D9, and D10 on a nano.

The output to the motor drivers works correctly. I can analogWrite() to them with no issues and even use libraries like TimerOne to write to them. They are programmed with a 0.2 ohm resistor to current limit at 2.5 amps, but I'm not sure if that's relevant. The current limiting does appear to work correctly.

However, for some reason the board absolutely refuses to work with any RC signal input library I've tried. RC Receiver kind of works, or at least the output on the motor driver changes when I change the input signal. It doesn't change correctly though, having very little variation in PWM duty cycle on the output. RCReceiver (different lib) doesn't work at all, sending a constant signal at about 50% duty cycle and a weirdly low pulse frequency to the motor, and ServoInput has the same result as RCReceiver.

Here is the code for the RC Receiver library test.

#include <RC_Receiver.h>
#include <TimerOne.h>
RC_Receiver receiver(0);


int read1;

int FWDwrite1A;



void setup() {
  Serial.begin(9600);
  Timer1.initialize(200);
}
void loop() {
  read1 = receiver.getRaw(1);

  FWDwrite1A = map(read1, 1000, 2000, 0, 255);
  analogWrite(9, FWDwrite1A);
  //Timer1.pwm(9, FWDwrite1A);
  digitalWrite(10, 0);
  Serial.println(FWDwrite1A);
}

Despite there being serial code, I am unable to access the serial monitor on this board at this time. The code is there from when I was testing this program on standard Uno R3s, and it works just fine on them although I have to substitute an LED for the motor output.

I have also placed an LED directly between pin 9 and ground, and the output on it is the same as the motor. This means the issue must be with the atmega somehow. Possibly the internal clock.

I have also attached a schematic of the motor driver board. It includes an AMS1117, but that was not soldered on the board I was testing with. Attempts that did use the AMS1117 yielded the same results. It also includes a second servo input, but using this input instead of the one on pin 0 changed nothing.

The reason the servo input is on pin 0 is because I want future support for more complex protocols.

Almost any additional information you may need is available, but I may take some time to post it due to school/sleep/general time zone mismatches.

I am going to bump this because it was posted last night, and because I have an idea for debugging. I wonder if the same thing would happen if I placed a standalone atmega328PB DIP chip on a breadboard and uploaded the same code do it. I'm unable to test this until later but depending on the results it could further debugging efforts.

On your custom board, could you confirm if the post #1 chip is an atmega328 or atmega328P. What are you using as a core to program it and what have you selected the chip as?

I am not aware of the availability of a DIP version for the atmega328PB. Could you elaborate a bit more?

Whoops sorry, the DIP version has a different suffix. The custom board uses an atmega328-AU that comes in a TQFP package. I'm using the nano core (328P) to write code but I'm uploading via avrdude, the command line, and a USBASP.

EDIT: There is a chance there is a pinout mismatch between the Nano core and the atmega on the board.

I would suggest using MiniCore and select the 328 (without P) for your board.

I'll look into MiniCore. I've heard of it but I haven't used it. Seems perfect for this application.

EDIT - How difficult would it be to make my own core? Is that worth my time?

I have never considered something like that so I will leave it to someone else to answer that question.
I am happy to use tried and tested cores by experts, like MiniCore, and concentrate on my own projects.

1 Like

I tried MiniCore. I got different results but the motor is still unresponsive to servo inputs - it just ran at full bore and continued running after I disconnected the servo input wire.

EDIT - This is the code I tried. I also tried using TimerOne.

#include <RC_Receiver.h>
#include <TimerOne.h>
RC_Receiver receiver(PIN_PD0);


int read1;

int FWDwrite1A;



void setup() {
  Serial.begin(9600);
  Timer1.initialize(200);
}
void loop() {
  read1 = receiver.getRaw(PIN_PD0);

  FWDwrite1A = map(read1, 1000, 2000, 0, 255);
  analogWrite(9, FWDwrite1A);
  //Timer1.pwm(PIN_PB1, FWDwrite1A);
  digitalWrite(PIN_PB2, 0);
  Serial.println(FWDwrite1A);
}

I just plugged an atmega into an uno and set all the fuses the same way as on the motor driver, then uploaded to it. It does exactly the same thing

I have also just discovered that a constantly on output will also happen if the uno doesn't get a signal. I think this issue might end up getting chalked up to the internal oscillator or something being terrible.
EDIT - I just ran the following programs on two boards. The first ran on an Uno wired to my motor driver and the second ran on the motor driver. The program on the motor driver should filter out any signals that aren't servo signals and... well the motor isn't moving. That means that the motor driver is not receiving the correct signals.

Update for anyone following this. The motor driver is able to receive digital inputs.

UPDATE - I just tried writing a servo signal from the motor driver and it was not read by another board.

Which RC receiver are you using and how have you wired it?
Just to check that you are using a PWM servo output from your RC receiver and not a PPM, SBUS or any other serial protocol output from the receiver.

For testing purposes I'm just using an Uno with a single servo.writeMicroseconds(1500); command in the void loop along with all the other servo setup stuff.

I am getting compilation errors when using minicore with your second sketch, so I created something that I think does what you want.

Taking a servo signal on pin 2 (not using pin 1 as that's the RX pin and connected to other HW on my nano.
Print the servo pulsewidth and next to it the mapped PWM value for analogwrite

I added a constrain to prevent out-of-bound PWM values

int read1;
int FWDwrite1A;

void setup() {
  Serial.begin(9600);
}
void loop() {
  read1 = constrain(pulseIn(2, HIGH, 250000), 1000, 2000);
  FWDwrite1A = map(read1, 1000, 2000, 0, 255);
  analogWrite(9, FWDwrite1A);
  Serial.print(read1);
  Serial.print("\t");
  Serial.println(FWDwrite1A);
}

Tested with a servo tester connected to pin2 and a led on pin 9.

or....If you want it without the printing it's a oneliner

void setup() {
}
void loop() {
  analogWrite(9, map(constrain(pulseIn(2, HIGH, 250000), 1000, 2000), 1000, 2000, 0, 255));
}

I will test this later.

EDIT - What exactly does the (2, HIGH, 250000) bit of the constrain function do?

that belongs to the "pulseIn" command

Syntax

pulseIn(pin, value)
pulseIn(pin, value, timeout)

I chose 250000 microseconds as a timeout so that you will not get 2 samples within the 20 milliseconds that the servo pulses are apart (50Hz) .
e.g. try lowering it to 15000 and look at the printout.

1 Like

I have uploaded your program and it didn't seem to work. I will further debug later using unos.

Bumping. Nothing has worked thus far. Is it worth just revising the PCB with a 16mHz crystal or am I missing something stupid?

Did my program work on your uno?

I never did do that. Mostly because I'm fairly certain it would work. I will try it when I get home.