If not working as expected

Hi I am trying to add a square wave channel to a to a sine wave generator by adding if function,

  if (sin(stp * i) > 0)
    {
      digitalWrite(PC13, 0);
    }
    else
    {
      digitalWrite(PC13, 1);
    }
    //////////////////////////////////

but it is not working. How do I fix this?

//+++++++++++++++++++++++++++++++++++++++
#define SAMPLES 130 // frequency adjustment
//+++++++++++++++++++++++++++++++++++++++
//#include <libmaple/dma.h>
dma_tube_config dma_cfg, dma_cfg2;
int flag = 0;
int flag1 = 0;
int out1 = PB7;
int val1[SAMPLES];

int16 shift = 0;

int amp = 40;
int cnt = 0;
int time_track = 0;
float stp = 6.2831 / SAMPLES;
int ret = 17;

//timer_dev *dev = PIN_MAP[out].timer_device;
//uint8 cc_channel = PIN_MAP[out].timer_channel;
timer_dev *dev1 = PIN_MAP[out1].timer_device;
uint8 cc_channel1 = PIN_MAP[out1].timer_channel;

void fun()
{
  flag++;
}
void fun1()
{
  flag1++;
}

void timer_conf()
{
  /////////////
  //  timer_dma_set_base_addr(dev, TIMER_DMA_BASE_CCR2);
  timer_dma_set_burst_len(dev1, 1);
  //  timer_dma_enable_req(dev, cc_channel1);
  //  timer_set_reload(dev, 102);
  //  timer_set_prescaler(dev, 0);
  ///////////////
  timer_dma_set_base_addr(dev1, TIMER_DMA_BASE_CCR2);
  timer_dma_set_burst_len(dev1, 1);
  timer_dma_enable_req(dev1, cc_channel1);
  timer_set_reload(dev1, 102);
  timer_set_prescaler(dev1, 0);
}

void dma_conf()
{
  dma_init(DMA1);
  /* T4C2 DMA C4 */
  //  dma_cfg.tube_dst = &(dev->regs.gen->DMAR);
  dma_cfg.tube_dst = &(dev1->regs.gen->DMAR);
  dma_cfg.tube_dst_size = DMA_SIZE_32BITS;
  //  dma_cfg.tube_src = val;
  dma_cfg.tube_src = val1;
  dma_cfg.tube_src_size = DMA_SIZE_32BITS;
  dma_cfg.tube_nr_xfers = SAMPLES;
  dma_cfg.tube_flags = DMA_CFG_SRC_INC | DMA_CFG_CIRC | DMA_CFG_CMPLT_IE;
  dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH1;
  dma_cfg.tube_req_src = DMA_REQ_SRC_TIM4_CH2;
  dma_cfg.target_data = 0;

  ret = dma_tube_cfg(DMA1, DMA_CH4, &dma_cfg);
}

void dma_start()
{
  dma_attach_interrupt(DMA1, DMA_CH4, fun);
  dma_enable(DMA1, DMA_CH4);
  timer_resume(dev1);
  dma_enable(DMA1, DMA_CH1);
  dma_enable(DMA1, DMA_CH2);

}

void init_wave()
{
  int i;
  for (i = 0; i < SAMPLES; i++)
  {
    //    val[i] = 40 + amp * sin(stp * i);
    val1[i] = 40 + amp * sin(stp * i);
    ////////////////////////////////////
    if (sin(stp * i) > 0)
    {
      digitalWrite(PC13, 0);
    }
    else
    {
      digitalWrite(PC13, 1);
    }
    //////////////////////////////////
  }
}

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

  int i;
  pinMode(out1, PWM);

  // pinMode(out1, OUTPUT);
  timer_conf();
  dma_conf();
  dma_start();
  init_wave();
}

void loop()

{


}

More details of the problem please

Print the value that you are testing. Is it what you expect it to be ?

It looks like you are doing integer arithmetic with variables that should be floating point.

1 Like

Without the added part, the program generates an 8 kHz sine wave on pin PB7 (stm32f103), when the if function is added, I expect a square wave on pin PC13, but there is no signal on PC13, and on PB7 the sine wave also disappears

is PB13 the same as LED_BUILTIN being set to OUTPUT in setup()?

yes

You do the digitalWrite()s in a function that is only called once, from setup().

I can't tell what you expect that to accomplish later.

This, BTW, is fine:

if (sin(stp * i) > 0)

if it was in a place where stp or i were varying over the domain of the sin() function.

a7

  // This is the sequence in setup()

  timer_conf();
  dma_conf();
  dma_start();
  init_wave();

Hi @tom321 ,

as @alto777 already posted the only place the led pin is changing is inside the function init_wave(). So it will be performed once and as quick as the controller handles the for-loop. It could be solved with a specific wave data array and DMA routine or a separate timer function.

I guess the compiler is clever enough to recognize that the term sin(stp * i) does not change inside the for-loop and it will use the value without calling the function again. It does not matter in a setup() function but it might be a good idea to store this kind of data if the same, unchanged value is used at different places in the code.

BTW: Shouldn't the function init_wave() be called before dma_start() as init_wave() creates the data that are used by the DMA routine? Not essential, but might be cleaner.

Have fun!
ec2021

How are you measuring this? If you try to make a measurement after the 130 iterations of the for loop have completed, you will see a constant LOW voltage on Pin 13 (assuming that LED_BUILTIN==13 on your board).

Probably because the variable PWM appears to be undefined, and because you call dma_conf() before calling init_wave().

Works for me. Of course there's no delay so writes changes occur very quickly

But it does, stp * i marches right from 0 to 2 * pi.

The expression guarding the digitalWrite()s yields zeros for the first half and ones for the second half of the circle.

But

while true in some sense, is not what @tom321 is going for. I think the intent is to have a square wave auto-interrupt-generated along side the sin wave.

For that, something will have to be done not just in setup() once. The stupid solution is to use init_wave() to build a second table for the digital output that will be the square wave.

I said it was stupid.

a7

looks like he's trying to generate a square wave by toggling an output pin. But without any delay, it's happening much faster then he expects, 16+msec

If you look at the entire sketch and squint, init_wave() serves to initialize an array used subsequently to provide a continuous sine wave output. Those calculations are done once at setup(), so speed isn't much of an issue.

Toggling an output bit there while building the table is nonsense.

Perhaps @tom321 will elaborate on the circuitry and what the idea of the sketch is with a bit more detail around IRS and DMA. There may be an easy way to set up (another) interrupt-driven function to do the toggling in synch.

a7

Hi, @tom321

What exact model Arduino are you using?

Tom.... :smiley: :+1: :coffee: :australia:

What I wanted to say is that term sin(stp * i) is used two times inside the for-loop and the value of (stp * i) does not change from the first to the second use.

I assume the compiler will recognize this case and not call sin() a second time with an identical value to shorten the execution time.

Sorry for the misunderstanding.

Creating a second wave table may not be the most elegant solution but it's a valid one that provides easy possibilities to change from square wave to other wave forms like sawtooth or triangle. And it's easy to implement a second DMA channel as the mechanism is already there.

It depends on what the TO wants to achieve... Which is still unknown.

ec2021

1 Like

stm32f103

It is look that there is no easy way to accomplish that.

This is not your first topic where you come to this conclusion. don't look for easy ways, start learning.

1 Like

The easiest way would be for @tom321 to actually read and respond to all comments made by others in the thread...

I learned that you also don't know how to solve the problem.