Go Down

Topic: Square wave function programming on Arduino Due (Read 364 times) previous topic - next topic

David_ZI

Dear all, can someone here help me to code the desired voltage profile "violet curve". The "red curve" is actual voltage profile which runs at the moment. But the "violet curve" profile is highly needed.
:smiley-confuse:
programm is not Ready...

Speklap

Use timers or millis() to configure an PWM (pulse width modulation) wave.

Outport is high -> high voltage
Outport is low -> low voltage

David_ZI

programm is not Ready...

horace

have a look at the tc_lib library for the Due
it contains useful functions for measurning and generating signals

Speklap

#4
May 16, 2018, 10:08 pm Last Edit: May 16, 2018, 10:09 pm by Speklap
My understanding is, you want a blocksignal with a period of about 200 ms and a duty cycle of 50%?

You can program a timer which generates an interrupt each 100ms. In the interrupt handler you can then toggle the output pin.

This code makes a 15kHz blockwave with 50% dutycycle. Credits to ard_newbie who posted it as an answer to my question couple of months ago.
Change the prescaler, RA and RC register to get the needed values

Code: [Select]

/**************************************************************************************/
/*       PWM pulses on TIOA0 (arduino pin 2) Frequency = 15 KHz, Duty cycle = 50%     */
/*       Interruptions on TIOA0 rising and falling edges                              */               
/**************************************************************************************/

void setup() {

  /*************  Timer Counter 0 Channel 0 to generate PWM pulses thru TIOA0  ************/
  PMC->PMC_PCER0 |= PMC_PCER0_PID27;       // TC0 power ON - Timer Counter 0 channel 0 IS TC0
 
  PIOB->PIO_PDR |= PIO_PDR_P25;           // PB25 is no more driven by the GPIO
  PIOB->PIO_ABSR |= PIO_PB25B_TIOA0;

  TC0->TC_CHANNEL[0].TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1  // MCK/2, clk on rising edge
                              | TC_CMR_WAVE               // Waveform mode
                              | TC_CMR_WAVSEL_UP_RC        // UP mode with automatic trigger on RC Compare
                              | TC_CMR_ACPA_CLEAR          // Clear TIOA0 on RA compare match
                              | TC_CMR_ACPC_SET;           // Set TIOA0 on RC compare match


  TC0->TC_CHANNEL[0].TC_RC = 2800;  //<*********************  Frequency = (Mck/2)/TC_RC  Hz = 15 KHz
  TC0->TC_CHANNEL[0].TC_RA = 1400;  //<********************   Duty cycle = (TC_RA/TC_RC) * 100  %  = 80 %

  TC0->TC_CHANNEL[0].TC_IER = TC_IER_CPCS       // Interrupt on RC compare match
                              | TC_IER_CPAS;    // Interrupt on RA compare match
                             
  NVIC_EnableIRQ(TC0_IRQn);                     // Interrupt enable
                           
  TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Software trigger TC0 counter and enable
}
void TC0_Handler()
{
 uint32_t status;
 status = TC0->TC_CHANNEL[0].TC_SR;  // Read and clear TC0 status register

 if(status & TC_SR_CPAS) {
  // Toggle pin 1
 }
 else  // if(status & TC_SR_CPCS)
  {
  // Toggle pin 2
 }
}
void loop() {
 
}

David_ZI

at the moment i have a function in my code which creates the "red curve" aka setpoint in the graph above. It takes a "setpoint" variable then ramps up to 3.0 Votls, then ramps down to 0.0 Volts with 0.02 Volt steps.

Please have a look at the code:
Code: [Select]
double setpoint_value_Ramp_Hold_Dump()
            {
              static unsigned long start_millis = 0;
              unsigned long current_millis;
              const unsigned long hold = 1;
              current_millis = millis();
                if (current_millis - start_millis >= hold)
                  {
                    start_millis += hold;
                      if(RampingUp)
                       {
                        setpoint += 0.02;
                        if (setpoint > 3.0)
                          {
                           setpoint = 3.0;
                           RampingUp = false;
                          }
                       }
                        else  // not RampingUp
                         {
                          setpoint -= 0.02;
                           if(setpoint < 0.0)
                            {
                             setpoint = 0.0;
                             RampingUp = true;
                            }
                         }
                   }
               }

There are no timers or counters employed as I understand. I also thought that Timers might be the right way to do it. But before starting to twiggle the Timers, maybe it might be possible to create the similar voltage profile by modifying the above mentioned function of my program. In order to change the "red curve " in graph look like the "violet " one.

programm is not Ready...

horace

is the actual real world sensor signal the black trace on the diagram in post #1 and you wish to convert this to the violet trace using an arduino? 
if so could you use an ADC to
1. sense the rising edge and output a high signal on a digital pin
2. sense the falling edge and output a low signal on a digital pin
if not could give us more details of the project, e.g. input signals and output required?

Go Up