Ledc, pwm esp32

Hello,
I m struggling with LEDC and interruption.
I want to generate 2 PWM signals of 200 us and 116 us.
For each 1 in a byte I want to get a PWM signal of 200 ms with a duty of 50% when gpio RISING.
For each 0 in a byte I want to get a PWM signal of 116 us with 50% duty when GPIO rising.
To test my programme I m reading the byte 0b11011101111011011011 in the interruption function but it does not work. The output on the oscilloscope is constant and does not fit with what I want to get.
I have taken a resolution of 8 bits and a corresponding duty of 127 to get 50%.
Thanks for your help


#include "driver/ledc.h"

// setting PWM properties
#define sig_1_freq 8621 // fréquence de 116µs 
#define sig_0_freq 5000 // fréquence de 200µs 
const int pin_channel = 0; // choix du canan PWM0
const int sig_resolution = 8; // resolution = 1 bit pour 2 valeurs 0 et 1
const int sig_duty = 127; // pour le rapport cyclique de 1/2 1 bit => 1/2^1
uint32_t sig_freq = sig_0_freq; // On part de la fréquence 5000

#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;
uint64_t v;


int msg; // 1 = marche;0 arret

const int dcc_pin = 19;  // Sortie du signal DCC     
const int pwn_pin = 18;  // Sortie du signal DCC envoi courant


struct __attribute__((packed)) t_message { // total de 48 bits à envoyer
   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 buildMessage(t_message& message, byte address, byte speedAndDir) {
  message.debut = 0b11011101111011011011;
  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 dumpMessageBits(t_message& message) {
 // int j=0;
  //uint64_t v;
  memcpy(&v, &message, sizeof v);

}




void setup() {
  Serial.begin(115200);
   pinMode(pwn_pin, OUTPUT); 
   ledcSetup(pin_channel,sig_freq, sig_resolution); // canal 0 frequence 5000 OU 8621  resolution 1 BIT 2 valeurs possibles 2^1=2
   ledcAttachPin(dcc_pin, pin_channel); /// pin 19 au canal pwm O
   ledcWrite(pin_channel,sig_duty);
  attachInterrupt(dcc_pin, dcc_sig_isr, RISING); // a chaque fois que le signal est HIGH interruption se déclenche
 
}
void dcc_sig_isr() {

for (int i=19;i>=0;i--) {
  if (bitRead(unMessage.debut,i)==1) {
    sig_freq=sig_1_freq;
    ledc_set_freq(LEDC_HIGH_SPEED_MODE, LEDC_TIMER_0, sig_freq);
  }else{
    sig_freq=sig_0_freq;
    ledc_set_freq(LEDC_HIGH_SPEED_MODE, LEDC_TIMER_0, sig_freq);
  }
}
}

 




// 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(3, 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);

}




  

Firstly, please use Ctrl-T to auto-format your code in the IDE as your formatting is presently just a little confusing.

I am a trifle concerned about the use of interrupts for this purpose but nevertheless

This sort of thing really needs machine coding. I am not sure whether it is the cause of the problem, but you really need to place the

at the start of the ISR, making sig_freq a static in order to make the time it takes for the interrupt to initiate be constant.

Hello Thanks Paul.
when I am using the following code in the ISR it s working well.
But in my previous code if I put ledc_set_freq at the beginning of the ISR I get the same result : a constant signal watever the frequence.
It s like the loop does not work as frequence is unchanged.
If you can help....thanks and regards


 if (sig_freq == sig_0_freq) sig_freq = sig_1_freq ; 
else sig_freq = sig_0_freq ;

  ledc_set_freq(LEDC_HIGH_SPEED_MODE, LEDC_TIMER_0, sig_freq); 

That is because the variable sig_freq must be declared at the beginning of the code as a "static" (or is that "global" - someone else may clarify) so that when set after it is used, it will be there ready for the next interrupt.

Otherwise it is only actually made locally each time the function is called. Just a bit of "C" strangeness. :grin:

I see but still does not work.
If I declare sig_freq as static uint32_t sig_freq; => there s no signal at all. If I declare static sig_freq=sig_0_freq I get a clear signal but only with the frequence 5000Hz. The variable does not change for sig_1_freq. I m loosing all my hair over this issue.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.