its very powerful indeed. tc pwm might be even better, but it has only 6 channels available and I need 8 pwm channels.
I could solve the issue by putting a 10k resistor as a pull down. Dont know why previously the 4.7k didnt work, it should have, probably a loose connection on the breadboard.
I of course ran into a different problem now.
My application is like this. I monitor a input trigger line. When it goes up, I need to generate a single pulse of predetermined freq on an output pin.
So what I do is like this -
do all the setup for the pwm configuration, including setting the timings etc.
infinite loop:
read trigger
if (trigger has gone up)
{
enable pwm channel
disable pwm channel
}
goto infinite loop
As per the documentation, when I enable a pwm channel, its supposed to start immediately. and when I do disable on a pwm channel, it will complete the current cycle and then stop. So if I do a enable and disable immediately, it should give me exactly one pulse.
The code is attached here.
#include <Arduino.h>
#include <SD.h>
#include <SPI.h>
#include <Ethernet.h>
// we use pin 34 and 35, which is pc02 and pc03
#define BITMAP 0x0C
// lets use PA0 for the trigger, which is pin CANTX0 or D69
#define TRIGGER_MASK 0x1
#define PWM_TOTAL_PERIOD 7000
#define PWM_DUTY_CYCLE 100
// this sets the clock. e.g. prescalar = 1 is MCK/2, prescalar = 6 is MCK/64
#define CLOCK_PRESCALAR 0x6
void setup()
{
Serial.begin(115200);
Serial.println("inside setup");
// enable clock for inputs or it wont work
pmc_enable_periph_clk(ID_PIOA);
// turn on clocking to PWM unit
pmc_enable_periph_clk (ID_PWM) ;
// lets set the trigger input register for gpio and input
REG_PIOA_PER = TRIGGER_MASK;
REG_PIOA_ODR = TRIGGER_MASK;
// Configure pin 34 (PC2) to be driven by peripheral B (PWM channel 0 L)
// enable pin PC02 and PC03 (pin 35), they are complimentary
REG_PIOC_OER = 0xC;
REG_PIOC_PDR = 0xC ; // disable PIO control
REG_PIOC_ABSR |= 0xC ; // switch to B peripheral
REG_PWM_DIS = 0x1; // disable channel 0
// set polarity to 1 and clock to PRESCALAR
// set DTHI to 1, so that both complimentary outputs are identical.
REG_PWM_CMR0 = CLOCK_PRESCALAR | PWM_CMR_DTHI | PWM_CMR_CPOL;
// set period and duty cycle
REG_PWM_CDTY0 = PWM_DUTY_CYCLE;
REG_PWM_CPRD0 = PWM_TOTAL_PERIOD;
/*
unsigned int pwm_pin = 34;
PIO_Configure( g_APinDescription[pwm_pin].pPort, PIO_OUTPUT_0, g_APinDescription[pwm_pin].ulPin, g_APinDescription[pwm_pin].ulPinConfiguration);
pwm_pin = 35;
PIO_Configure( g_APinDescription[pwm_pin].pPort, PIO_OUTPUT_0, g_APinDescription[pwm_pin].ulPin, g_APinDescription[pwm_pin].ulPinConfiguration);
*/
/*
unsigned int channel = 0;
PWMC_ConfigureChannelExt( PWM, channel, CLOCK_PRESCALAR, 0, PWM_CMR_CPOL,
0, 0, PWM_CMR_DTHI, 0 );
PWMC_SetPeriod (PWM, channel, PWM_TOTAL_PERIOD) ; // period = 700 pwm clocks (60kHz)
*/
Serial.println("leaving setup");
}
void loop()
{
unsigned int old_trigger=0;
INFINITE_LOOP:
unsigned int new_trigger = (REG_PIOA_PDSR & TRIGGER_MASK);
// find trigger going from 0 to 1
boolean ch_triggered = false;
if (old_trigger == 0 && new_trigger == 1)
ch_triggered = true;
if (ch_triggered == true)
REG_PWM_ENA = 0x1;
// commenting out this delay has impact
delayMicroseconds(5);
old_trigger = new_trigger;
if (ch_triggered == true)
REG_PWM_DIS = 0x1;
goto INFINITE_LOOP;
}
I generate the trigger on uno and feed it to due (thru a voltage divider for 3.3v).
The issue I face is that I dont see one output per trigger. It goes up only once in a while. then I added the 5us delay in the loop. Now it functions better. If I change the timings of the pwm pulse (duty and period) and make it very large (say 100ms, 200ms), the 5us delay is not enough. It keeps missing outputs.
I also tried the code in comments, but didnt make a difference.
How do i make it stable, i.e. whenever I get a trigger, I show a single pulse. Without a delay.