I want to think through a project with the group's help.
I have plenty of experience with Arduino projects, but very little with the ATTiny variants.
I am considering a dead bug ATTiny85 (or any that fit my needs). Small physical size will be a plus.
The general synopsis of my project is that I have a radio control truck that I want to modify.
The term for what I want is called "dig" where both axles can turn for normal driving, but they can be driven differently when the need arises. Typical use is to stop the rear and power the front axle for tighter turning. This is not a 'go fast' truck but a rock crawler.
Currently the truck has a receiver/ESC combo.
It exposes channel 1 for the steering servo.
Channel 2 is used for the internal ESC.
It exposes channel 3 for auxiliary use.
I want to replace the single motor with 2 independent motors, one for the front axle and one for the rear axle.
I want to replace the receiver/ESC combo with a standalone receiver and 2 ESCs.
The receiver will support PPM so all the channels can be read using a single arduino pin.
I want to sit the arduino between the receiver and the servo and ESCs.
I will read in all of the channel values from the receiver PPM pin.
I will write the steering value to the steering servo.
I will use the auxiliary channel to determine throttle mode.
As an example, I might use 2 modes. If the aux is low (less than 1500) then the throttle value is sent to both ESCs.
If the aux is high (more than 1500) I will sent the throttle value to the front ESC and send a stop value (1500) to the rear ESC.
So, one PPM signal in. 3 servo signals out.
Is this something that an ATTiny85 can do?
If the ESCs provide a regulated 5v, will I be able to simply use the naked ATTiny85 chip or will it need other hardware?
Oh, other than a programming board. Something like this?
And if I want to go with a SMD version, I can use this?
I am not familiar with that line of microcontrollers.
Is it compatible with the Arduino IDE?
What hardware is needed to program it?
I was wondering if with my limited requirements, I could get away without actually timing a servo signal.
Let me use the steering signal as an example.
Steering is channel 1.
After the PPM frame end signal (low for some long period of time) when the PPM goes high, I set the steering servo signal high.
The PPM signal will go low and when it goes high again, that is the end of the steering signal and the start of channel 2, throttle. So set the steering servo signal low.
Would this effectively pass through the receiver steering value to the steering servo without using a timer?
Similarly, the throttle can be passed through to both ESCs if the aux channel is low.
If it is high, I need to leave ESC2 high for 1500 microseconds, regardless of what gets passed through to ESC1.
Try compiling some code for the ATtiny using the servo library. IIRC, it only needs one timer. No idea if it would work, but worth seeing if the compiler barfs at least.
I do have a programmer and a sleeve of ATTiny85's from a previous project that went a different direction.
I'll start with Blink and Sweep and go from there.
I had hoped for a smaller form factor than that.
If all else fails, I do have some of these laying around.
And with more IO, I can do things like put turn signals on my toy truck.
But I think that I am going plow forward with the ATTiny85.
Foe ease of use I am using the digispark board to work ouit all the code before I start soldering on the dead bug.
I have blink running. It was a pain remembering when to disconnect and when to connect during the programming but google helped.
Next up is sweep and then try to read the PPM signal.
Who can help educate me on setting up a pin change interrupt on the tiny? Rising if possible.
I want to directly drive servo pins based on the rising points of the PPM signal.
I want to watch the PPM signal with a rising pin change interrupt. This old stackexchange post indicates that PB2 INT0_vect is what I want.
I have not yet been able to pull together enough to understand how to set it up.
Edit: I guess that I should follow the advice that is so very frequently skipped. Post my best attempt and describe the mismatch between my expectations and actual.
#include <avr/interrupt.h>
volatile uint8_t currentServo = 0;
volatile unsigned long previousMillis;
volatile unsigned long currentMillis;
void setup() {
pinMode(PB0, OUTPUT);
GIMSK = 0b01100000; //6 for external interrupts and 5 for pin change
PCMSK = 0b00000100; //PB2 I hope
MCUCR = 0b00000011; //1 and 0 set to 11 for RISING
previousMillis = millis();
sei();
}
void loop() {
}
ISR(PCINT0_vect)
{
currentMillis = millis();
if (previousMillis - currentMillis > 4) {
//just completed frame end so this is the rise for the first channel
digitalWrite(PB0, HIGH);
}
else
{
digitalWrite(PB0, LOW);
}
previousMillis = currentMillis;
}
I expected the servo attached to PB0 to move when I move the steering on my transmitter.
It does not.
Edit2: For clarification, this code DOES move my servo through a sweep. I wrote it to make sure I could move a servo, and this was before trying to put in the PPM reading.
void setup() {
pinMode(PB0, OUTPUT);
}
void loop() {
for (uint16_t i = 1100; i < 1900; i++) {
digitalWrite(PB0, HIGH);
delayMicroseconds(i);
// 1 millisecond determines the servo going forwards
digitalWrite(PB0, LOW);
delay(19);
}
for (uint16_t i = 1900; i > 1100; i--) {
digitalWrite(PB0, HIGH);
delayMicroseconds(i);
// 1 millisecond determines the servo going forwards
digitalWrite(PB0, LOW);
delay(19);
}
}
I was going to go for an Edit3 but eventually I'll end up stepping on someone's toes if they try to reply.
I think that rather than PCINT0_vect I should use INT0_vect
I want the external interrupt on PB2.
Again, I think. Is that what would fire hooking the output of the receiver's PPM to PB2 on the ATTiny85?
So, latest code.
For the moment, I am just trying to get the first channel to be sent to the single servo.
#include <avr/interrupt.h>
volatile uint8_t currentServo = 0;
volatile unsigned long previousMillis;
volatile unsigned long currentMillis;
#define servoPin PB0
void setup() {
pinMode(servoPin, OUTPUT);
GIMSK = 0b01000000; //6 for external interrupts
PCMSK = 0b00000100; //PB2 I hope
MCUCR = 0b00000011; //1 and 0 set to 11 for RISING
previousMillis = millis();
sei();
}
void loop() {
}
ISR(INT0_vect)
{
currentMillis = millis();
if (previousMillis - currentMillis > 4) {
//just completed frame end so this is the rise for the first channel
digitalWrite(servoPin, HIGH);
}
else
{
digitalWrite(servoPin, LOW);
}
previousMillis = currentMillis;
}
I put a pic of the signal at the bottom.
I do realize (admittedly at 3am) that I have too much code in the ISR.
Minimal ISR Vince. Set a flag. Let the loop() process.
Also, I think that the project guidance part of this question has been answered. I do have programming question still to resolve but I think that will be better met on the Programming forum. I will post a link to that post shortly.
I have had success reading a PPM signal from a radio control hobby receiver and driving servos using an UNO. I am trying to do this using an ATTiny85.
Ultimately I want to drive a servo and 2 ESCs but for now I just want to use the first channel of the PPM signal to drive a single servo.
I do not know if I have the interrupt set up properly for the Tiny.
I have attacked a wiring diagram.
I have successfully tested driving a servo from the Tiny so I feel confident that my wiring for the servo is accurate.
I have code below that is my best attempt to use the timing of the first channel of the PPM signal to drive the servo.
I expect the sketch to move the servo when I wiggle the steering on the transmitter.
Instead, nothing happens.
unsigned long previousMillis;
volatile unsigned long currentMillis;
volatile bool processISR = false;
#define servoPin PB0
void setup() {
pinMode(servoPin, OUTPUT);
GIMSK = 0b01000000; //6 for external interrupts
PCMSK = 0b00000100; //PB2 I hope
MCUCR = 0b00000011; //1 and 0 set to 11 for RISING
previousMillis = millis();
sei();
}
void loop() {
if (processISR) {
if (previousMillis - currentMillis > 4) {
//just completed frame end so this is the rise for the first channel
digitalWrite(servoPin, HIGH);
}
else
{
digitalWrite(servoPin, LOW);
}
previousMillis = currentMillis;
processISR = false;
}
}
ISR(INT0_vect)
{
currentMillis = millis();
processISR = true;
}
My thought is that if I see the PPM rising after more than 4 millis form the previous rising, then this is the start of the first channel after the long frame end period.
Set the servo pin high.
Then when I see the PPM rising again, set the servo pin low.
In this simple version I will also set the servo pin low for all the other channels in the PPM signal set but that will not affect anything.
I should have a workable servo signal of the duration defined by channel 1 of the PPM signal.
If I can get this working then I will add logic to process other channels from the PPM signal set and perform some custom changes to them. But first I want to make the interrupts work and hove not done so yet.