Closed reduzent closed 9 months ago
Hm.. now while reading the code, I wonder whether it is possible to perform the NmraDcc.init() function in the main loop, setting it to a pin with no DCC signal, and then later back to pin 2.
It worked by detaching the interrupt while the servo is moving (see line 59):
#include <EEPROM.h>
NmraDcc Dcc ;
DCC_MSG Packet ;
const int adresse = 25;
const int LED = 4;
const int relay = 3;
const int servo = 1;
const int pos_straight = 93;
const int pos_turn = 156;
bool state = LOW;
bool got_packet = false;
void servo_pulse(int pin, int pos){
int pulse = map(pos,0, 180, 850, 2050);
digitalWrite(pin, HIGH);
delayMicroseconds(pulse);
digitalWrite(pin, LOW);
delay(21);
}
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower )
{
switch(Addr){
case adresse:
if(Direction < 1){
state = LOW;
}else{
state = HIGH;
}
got_packet = true;
EEPROM.write(adresse, state);
break;
default:
break;
}
}
void setup()
{
Dcc.pin(0, 2, 1);
Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0 );
pinMode(LED, OUTPUT);
pinMode(relay, OUTPUT);
pinMode(servo, OUTPUT);
state = EEPROM.read(adresse);
digitalWrite(LED, state);
digitalWrite(relay, state);
}
void loop()
{
Dcc.process();
if ( got_packet ) {
detachInterrupt(0);
if (state) {
for (int i = pos_straight; i <= pos_turn; i++) {
servo_pulse(servo, i);
}
digitalWrite(LED, HIGH);
digitalWrite(relay, HIGH);
state = false;
} else {
for (int i = pos_turn; i >= pos_straight; i--) {
servo_pulse(servo, i);
}
digitalWrite(LED, LOW);
digitalWrite(relay, LOW);
state = true;
}
got_packet = false;
Dcc.pin(0,2,1);
Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0 );
}
}
closed
Hi Roman,
Sorry, I’ve been away on holiday, but I see you have figured out how to achieve what you needed to do.
We’d have to add pause()/resume() methods to do what you want, but your solution is probably ok.
I don’t think I’ve tried to drive servos from a Tiny85, but I’m a bit surprised you had issues as the AVRTinyCore has Tiny-specific support for servos, but obviously, it's still CPU load dependant…
Regards
Alex Shepherd
On 14/02/2024, at 12:30 AM, Roman Haefeli @.***> wrote:
It worked by detaching the interrupt while the servo is moving (see line 59):
include
NmraDcc Dcc ; DCC_MSG Packet ;
const int adresse = 25;
const int LED = 4; const int relay = 3; const int servo = 1; const int pos_straight = 93; const int pos_turn = 156;
bool state = LOW; bool got_packet = false;
void servo_pulse(int pin, int pos){ int pulse = map(pos,0, 180, 850, 2050); digitalWrite(pin, HIGH); delayMicroseconds(pulse); digitalWrite(pin, LOW); delay(21); }
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) { switch(Addr){ case adresse: if(Direction < 1){ state = LOW; }else{ state = HIGH; } got_packet = true; EEPROM.write(adresse, state); break; default: break; } }
void setup() { Dcc.pin(0, 2, 1); Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0 ); pinMode(LED, OUTPUT); pinMode(relay, OUTPUT); pinMode(servo, OUTPUT); state = EEPROM.read(adresse); digitalWrite(LED, state); digitalWrite(relay, state);
}
void loop() { Dcc.process(); if ( got_packet ) { detachInterrupt(0); if (state) { for (int i = pos_straight; i <= pos_turn; i++) { servo_pulse(servo, i); } digitalWrite(LED, HIGH); digitalWrite(relay, HIGH); state = false; } else { for (int i = pos_turn; i >= pos_straight; i--) { servo_pulse(servo, i); } digitalWrite(LED, LOW); digitalWrite(relay, LOW); state = true; } got_packet = false; Dcc.pin(0,2,1); Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0 ); }
} `` — Reply to this email directly, view it on GitHub https://github.com/mrrwa/NmraDcc/issues/77#issuecomment-1941286138, or unsubscribe https://github.com/notifications/unsubscribe-auth/AB5Y53ID3PTTGBUTJDLG3IDYTNFEDAVCNFSM6AAAAABDDBHLWKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNBRGI4DMMJTHA. You are receiving this because you are subscribed to this thread.
(It feels a bit awkward to ask questions in GitHub. If there is a better place, please let me know.)
I'm trying to build a turn-out decoder with an ATTiny85. I couldn't find a servo library that doesn't interfere with NmraDcc. So I decided to create the pulses in the code. However, while there is a DCC signal on the tracks, the servo becomes jittery. I guess that is because the interrupt has more priority than the delayMicroseconds() function. So, i thought about turning DCC reading off while the servo is moving. My idea basically is:
I'm aware that I would miss packets during the time DCC reading is turned off, but I don't have a need to switch turn-outs in quick succession.
So, is there a way to disable DCC reading termporarily? Or is there another way to get jitterless servo control?
This is the code I'm currently using, which disables the pulse after switching so that the servo stops trembling. It works, but it would be nice if I could move the servo slowly and steadily: