Hello everyone,
I have an issue for my interruption function. I want to read the unint_64 v bit per bit: when bit=1 then dcc_sig_freq=dcc_sig_1_freq (8261 Hz, 50% duty/resolution 11), when bit=0 then dcc_sig_freq=dcc_sig_0_freq (5000 Hz, 50% duty/resolution 11).
The problem I am facing with is when I loop with while for example and I put the 48 bits in a table, the esp32 is rebooting all the time. How can I avoid this? And how each bit of unint_64 v can be read with the good frequence without causing rebooting? Thanks
#include "driver/ledc.h"
volatile uint64_t masque;
volatile uint64_t dccBit;
volatile int trame[48];
volatile int trame_simplifie[48];
#define CRAN_0 0
#define CRAN_1 1
#define CRAN_2 2
#define CRAN_IDLE 5
byte dccSpeed;
byte addr;
byte adresse;
byte vitesse;
byte cksum;
int msg; // 1 = forward;0 stop
const int dcc_pin = 19; // DCC signal
const int pwn_pin = 18; //switch off/on
// setting PWM properties
#define dcc_sig_1_freq 8621 // = 115,99 microseconds
#define dcc_sig_0_freq 5000 // 200µs 5000 Hz donne 200 microseconds
const int dcc_pin_channel = 0; // channel PWM 0
unsigned int dcc_sig_resolution = 11; // resolution at 11
unsigned long dcc_sig_duty = 1024; // duty 50% is 1024
uint32_t dcc_sig_freq = dcc_sig_1_freq; // on part de la fréquence du bit 1 toutes les trames commencent par une série de 20 bits a 1
struct __attribute__((packed)) t_message { // 48 bits to send
uint64_t stop: 1; // 1 bit à 1
uint64_t cksum: 8; // 8 bits de verification
uint64_t zero2: 1; // 1 bit à 0
uint64_t speeddir: 8; // 8 bits de direction et de vitesse
uint64_t zero1: 1; // 1 bit à 0
uint64_t address: 8; // 8 bits d'adresse
uint64_t start: 1; // 1 bit à 0
uint64_t debut: 20; // 20 bits à 1
};
void dumpMessageBits(t_message& message) {// message to send
int j=0;
uint64_t v;
memcpy(&v, &message, sizeof v);
//for (int8_t i = 47; i >=0; --i
// ) Serial.print(bitRead(v, i) ? '1' : '0');
// Serial.println();
}
void buildMessage(t_message& message, byte address, byte speedAndDir) {
message.debut = 0b11111111111111111111;
message.start = 0b0;
message.address = address;
message.zero1 = 0b0;
message.speeddir = speedAndDir;
message.zero2 = 0b0;
message.cksum = address ^ speedAndDir; // au hasard, prendre les bons octets
message.stop = 0b1;
dumpMessageBits(message);
}
t_message unMessage;
void dcc_sig_isr() {// interruption function I want that for each bit in Uint_64 v when bit = 1 then dcc_sig_freq=1 or when bit = 0 then dcc_sig_freq=0. In order to make thing easier
if (dcc_sig_freq == dcc_sig_0_freq) dcc_sig_freq = dcc_sig_1_freq ;
else dcc_sig_freq = dcc_sig_0_freq ;
ledc_set_freq(LEDC_HIGH_SPEED_MODE, LEDC_TIMER_0, dcc_sig_freq);
}
//}
//}
void setup() {
Serial.begin(115200);
pinMode(pwn_pin, OUTPUT);
// configuration du canal pwm 0 avec une fréquence et la résolution
ledcSetup(dcc_pin_channel, dcc_sig_freq, dcc_sig_resolution); // on set up le canal avec une résolution de 1 bit cad 50%
ledcAttachPin(dcc_pin, dcc_pin_channel); /// et ensuite on l attache au PIN19
ledcWrite(dcc_pin_channel, dcc_sig_duty);
// programme l'interruption à la fin de la période
attachInterrupt(dcc_pin, dcc_sig_isr, RISING); // l'interruption "dcc_sig_isr" provoquée à la fin de chaque période (voire au début de la suivante) =>moi non plus
}
// fonction de calcul 3 octets
void SpeedAndDir(byte addr, byte SelectCran, byte SelectSpeed, bool SelectDirection) // vecteur de direction et de vitesse
{
byte type;
byte ext;
byte dir;
byte cksum=0;
uint64_t paquet=0;
switch(SelectCran) {
case 0: ////DCC_PACKET_TYPE_STEP_14
dccSpeed=map(SelectSpeed,0,128,0,14);
if (dccSpeed) dccSpeed++; // pas de cran 1
dir=(SelectDirection?0x60:0x40)|dccSpeed;
break;
case 1: ///DCC_PACKET_TYPE_STEP_28
dccSpeed=map(SelectSpeed,0,128,0,28);
if (dccSpeed) dccSpeed+=3; // pas de cran 1,2,3
ext=(((dccSpeed&0x01)<<5)|dccSpeed)>>1; ///
dir=(SelectDirection?0x60:0x40)|ext;
break;
case 2: //DCC_PACKET_TYPE_STEP_128;
dccSpeed=map(SelectSpeed,0,128,0,126);
if (dccSpeed) dccSpeed++; // pas de cran 1
dir=(SelectDirection?0x60:0x40)|dccSpeed;
break;
case 5: //IDLE;
dir=0b00000000;
break;
}
buildMessage(unMessage, addr,dir);
}
void loop() {
SpeedAndDir(32, CRAN_1,101,1);
if (Serial.available() )
msg = Serial.parseInt(); // Lit le message reçu et l'affiche sur le moniteur
(msg)?digitalWrite(pwn_pin,HIGH):digitalWrite(pwn_pin,LOW);
Serial.print(msg);
delay(500);
}