Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unstable datastream (UART with interrupts)/ DMX implementation #62

Open
kokospalme opened this issue Apr 18, 2024 · 0 comments
Open

unstable datastream (UART with interrupts)/ DMX implementation #62

kokospalme opened this issue Apr 18, 2024 · 0 comments

Comments

@kokospalme
Copy link

kokospalme commented Apr 18, 2024

the project: I want to dim an RGB-LED with PWM (MCU: STM8S103). The amount of dimming should be received as a datastream over DMX which is implemented via serial.
the problem: When I send data on a specific channel, the data is received, but there's a shift in the channel... So if I send data on channel 0 (DMXchannel 1), the channel which receives the data is drifting from 0 to 511, or even no data is received. So the system seem to be very unstable. Does someone know what could be the problem? here is my sktech:

/*
18.4.24, DMX sketch
DMX receiving-sketch
based on the uart loopback example: https://registry.platformio.org/platforms/platformio/ststm8/examples/spl-uart-loopback
PWM implementation based on: https://embedded-lab.com/blog/starting-stm8-microcontrollers/20/
*/

/* Includes ------------------------------------------------------------------*/
#include <Arduino.h>

/*  Defines -----------------------------------------------------------------*/
#define DMX_CHANNEL_COUNT 512 //all 512 DMX channel
#define DMX_CHANNEL_LED 1 //DMX Data on channel 1
volatile bool dmxMessageStarted = false;  //true if databytes are received 
volatile bool dataFree = false; //true if nothing is written in array by interrupt
volatile uint8_t dmxData[DMX_CHANNEL_COUNT];  //array to store DMX data in
volatile uint16_t dmxIndex = 0;

/* Private function prototypes -----------------------------------------------*/
static void CLK_Config(void);
static void UART_Config(void);
void GPIO_setup(void);
void TIM2_setup(void);

void main(void)
{
  
  pinMode(LED_BUILTIN, OUTPUT);

  CLK_Config(); //configure prescaler
  GPIO_setup();
  TIM2_setup();
  UART_Config();  //configure UART

  while(TRUE)
  {
    if(dataFree){ //if data array is not used by interrupt
      TIM2_SetCompare1(dmxData[DMX_CHANNEL_LED-1]);
      TIM2_SetCompare2(dmxData[DMX_CHANNEL_LED]);
      TIM2_SetCompare3(dmxData[DMX_CHANNEL_LED+1]);
      // TIM2_SetCompare3(128);  //Test-data on pin PA3
    }
  };
}


static void CLK_Config(void)
{
    /* Initialization of the clock */
    /* Clock divider to HSI/1 */
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);


    //  reset clock
    CLK_DeInit();

    // Deactivate external and internal oscillator, activate internal oscillator
    CLK_HSECmd(DISABLE);
    CLK_LSICmd(DISABLE);
    CLK_HSICmd(ENABLE);
    // Wawait until oscillator is stable
    while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);

    // Clock Switching
    CLK_ClockSwitchCmd(ENABLE);
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
    CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);

    // config for clock switching
    CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI,
    DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);

    // Deactivate clock for peripherals that are not required
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, ENABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, ENABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, DISABLE);
}

void GPIO_setup(void)
{
      GPIO_DeInit(GPIOA);
      GPIO_Init(GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_HIGH_FAST);

      GPIO_DeInit(GPIOD);
      GPIO_Init(GPIOD, ((GPIO_Pin_TypeDef)GPIO_PIN_3 | GPIO_PIN_4),
                GPIO_MODE_OUT_PP_HIGH_FAST);
}

// initialize timer 2 for PWM
void TIM2_setup(void)
{
      
      TIM2_DeInit();  // reset timer 2
      TIM2_TimeBaseInit(TIM2_PRESCALER_32, 255);  // Timer 2 als Zeitbasis mit Vorteiler 32 und Periodenwert 1000 initialisieren
      TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 255, // set timer 2 channel 1 as pwm, activate output, pulse and polarity
                   TIM2_OCPOLARITY_HIGH);

      TIM2_OC2Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 255,// set timer 2 channel 2 as pwm, activate output, pulse and polarity
                   TIM2_OCPOLARITY_LOW);

      TIM2_OC3Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, 255, // set timer 2 channel 3 as pwm, activate output, pulse and polarity
                   TIM2_OCPOLARITY_HIGH);
      TIM2_Cmd(ENABLE); // activate timer 2
}

void UART_Config(void)
{
  UART1_DeInit();
  
  // Configure UART1 for DMX mode
  UART1_Init(250000, 
             UART1_WORDLENGTH_8D, 
             UART1_STOPBITS_2, // 2 Stop-Bits für DMX
             UART1_PARITY_NO,
             UART1_SYNCMODE_CLOCK_DISABLE,
             UART1_MODE_RX_ENABLE);
  
  // Enable DMX receiver interrupt
  UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);
  
  // Enable global interrupts
  enableInterrupts();
}



INTERRUPT_HANDLER(UART1_RX_IRQHandler, 18)
{
  if (UART1_GetITStatus(UART1_IT_RXNE) != RESET)
  {
    uint8_t receivedData = UART1_ReceiveData8(); //  receive data

    if (dmxMessageStarted)
    {
      dataFree = false;
      dmxData[dmxIndex] = receivedData; // write data in array
      dmxIndex++;
      if (dmxIndex >= DMX_CHANNEL_COUNT)
      {

          dmxIndex = 0;
          dmxMessageStarted = false;
      }
    }
    else
    {
        // break signal
        if (receivedData == 0)
        {
            // digitalWrite(LED_BUILTIN, HIGH);
            dataFree = true;
            dmxMessageStarted = true; // begin of a new DMX message
            dmxIndex = 0; // reset index
        }
    }
  }
}
@kokospalme kokospalme changed the title no PWM when using UART with interrupts unstable datastream (UART with interrupts)/ DMX implementation Apr 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant