<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="bbPress/1.0.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>LeafLabs Garden &#187; Topic: manually implement PWM</title>
		<link>http://forums.leaflabs.com/topic.php?id=10191</link>
		<description>A place to share, learn, and grow...</description>
		<language>en-US</language>
		<pubDate>Fri, 22 Jan 2016 00:17:32 +0000</pubDate>
		<generator>http://bbpress.org/?v=1.0.2</generator>
		<textInput>
			<title><![CDATA[Search]]></title>
			<description><![CDATA[Search all topics from these forums.]]></description>
			<name>q</name>
			<link>http://forums.leaflabs.com/search.php</link>
		</textInput>
		<atom:link href="http://forums.leaflabs.com/rss.php?topic=10191" rel="self" type="application/rss+xml" />

		<item>
			<title>stephanschulz on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22315</link>
			<pubDate>Thu, 07 Feb 2013 20:02:20 +0000</pubDate>
			<dc:creator>stephanschulz</dc:creator>
			<guid isPermaLink="false">22315@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;to clarify the code i posted works fine. so no need to go back to use digitalWrite()&#60;/p&#62;
&#60;p&#62;i was even thinking of replacing the gpio_write_bit with gpio_toggle_bit which mean i don't have to store the bit state.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22313</link>
			<pubDate>Thu, 07 Feb 2013 19:20:51 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">22313@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;stephanschulz - I would suggest trying to slow everything, and use digitalWrite() to get something working.&#60;/p&#62;
&#60;p&#62;Once speed matters, you might want to look at an approach to quickly changing a pin:&#60;br /&#62;
&#60;a href=&#34;http://forums.leaflabs.com/topic.php?id=737#post-22300&#34; rel=&#34;nofollow&#34;&#62;http://forums.leaflabs.com/topic.php?id=737#post-22300&#60;/a&#62;
&#60;/p&#62;</description>
		</item>
		<item>
			<title>stephanschulz on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22293</link>
			<pubDate>Wed, 06 Feb 2013 11:15:36 +0000</pubDate>
			<dc:creator>stephanschulz</dc:creator>
			<guid isPermaLink="false">22293@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;here my progress.&#60;br /&#62;
i have an array of 16 pins that each are at a different dimming stage.&#60;/p&#62;
&#60;p&#62;i found one solution to gbulmer suggestion for eliminating the digitalWrite(). which is using gpio_write_bit(GPIOA, LED_BIT_ARRAY[i],dimStates[i]);&#60;/p&#62;
&#60;p&#62;next would be to look in to writing to the whole port at once.&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;#include &#38;lt;gpio.h&#38;gt;

volatile unsigned int counter = 0;
unsigned long myTimer = 0;
int dim = 0;
int dir = 1;

int ledAmt = 16;
int counterLimit = 160;

boolean dimStates [] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
volatile int dimValue [] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
const char ledPin[] = {
  15,16,17,18,19,20,21,22,27,28,29,30,31,0,1,6};

const int LED_PORTref_ARRAY[] = {
  1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0};
const int LED_BIT_ARRAY[] = {
  7,6,5,4,3,15,14,13,8,15,14,13,12,11,10,5};

//15 ,16 ,17 ,18 ,19 ,20  ,21  ,22  ,27 ,28  ,29  ,30  ,31  ,0   ,1   ,6
//b7 ,b6 ,b5 ,b4 ,b3 ,a15 ,a14 ,a13 ,a8 ,b15 ,b14 ,b13 ,b12 ,b11 ,b10 ,a5 

int dimDir [] = {
  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};

void handler_t(void) {
  for(int i=0; i&#38;lt;ledAmt; i++){
    if(dimValue[i] &#38;gt; counter){
      dimStates[i] = true;
    }
    else{
      dimStates[i] = false;
    }

    if(LED_PORTref_ARRAY[i] == 0) gpio_write_bit(GPIOA, LED_BIT_ARRAY[i],dimStates[i]);
    if(LED_PORTref_ARRAY[i] == 1) gpio_write_bit(GPIOB, LED_BIT_ARRAY[i],dimStates[i]);
    //digitalWrite(ledPin[i],dimStates[i]);

  }

  counter++;
  if(counter &#38;gt; counterLimit) counter = 0;
}

void setup(void) {

  for(int i=0; i&#38;lt;ledAmt; i++){
    pinMode(ledPin[i],OUTPUT);
    dimValue[i] = counterLimit/ledAmt * i;
  }

  pinMode(BOARD_LED_PIN,OUTPUT);

  Timer2.setPrescaleFactor(1);
  Timer2.setOverflow(500); //1079);
  Timer2.attachCompare1Interrupt(handler_t);
}

void loop(void) {
  if(millis() - myTimer &#38;gt; 15){
    myTimer = millis();
    toggleLED();

    for(int i=0; i&#38;lt;ledAmt; i++){
      dimValue[i] += dimDir[i];
      if(dimValue[i] &#38;gt; counterLimit &#124;&#124; dimValue[i] == 0) dimDir[i] = -dimDir[i];
    }

  }

}&#60;/code&#62;&#60;/pre&#62;</description>
		</item>
		<item>
			<title>gbulmer on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22275</link>
			<pubDate>Tue, 05 Feb 2013 11:47:24 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">22275@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;stephanschulz - Good progress.&#60;/p&#62;
&#60;p&#62;Let me offer a few suggestions.&#60;br /&#62;
An idiomatic way of changing the sign of a number is &#60;code&#62;dir = -dir;&#60;/code&#62;&#60;/p&#62;
&#60;p&#62;Do you understand the meaning of the type qualifier &#60;code&#62;volatile&#60;/code&#62;?&#60;br /&#62;
There are a bunch of places that explain its meaning, for example:&#60;br /&#62;
&#60;a href=&#34;http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html&#34; rel=&#34;nofollow&#34;&#62;http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;You will need to apply &#60;code&#62;volatile&#60;/code&#62; to variable definitions to reliably communicate values to the interrupt handler.&#60;/p&#62;
&#60;p&#62;It is possible to directly set the state of a GPIO pin if you know its address, e.g. &#60;code&#62;*PORTD_PIN5 = ledState;&#60;/code&#62;&#60;br /&#62;
This runs in about 1/20th (maybe faster) the time of a &#60;code&#62;digitalWrite()&#60;/code&#62;.&#60;br /&#62;
Hence using it in the interrupt handler would drastically reduce the time spent servicing the timer interrupt.&#60;br /&#62;
Further, upto 16pins, in the same port, can be written in one assignment. That would ensure the PWM signal for multiple pins would be synchronised.&#60;/p&#62;
&#60;p&#62;This isn't relevant now, but might become useful. There are several threads on the forum about using that technique, and you might want to resurrect one if it isn't clear.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>stephanschulz on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22272</link>
			<pubDate>Tue, 05 Feb 2013 10:01:38 +0000</pubDate>
			<dc:creator>stephanschulz</dc:creator>
			<guid isPermaLink="false">22272@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;thanks for pointing me to the thx_pwm example.&#60;/p&#62;
&#60;p&#62;i made this like test code based on the example.&#60;/p&#62;
&#60;p&#62;next step is making 16 independent LEDs.&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;boolean ledState = false;

unsigned int counter = 0;
unsigned long myTimer = 0;
int dim = 0;
int dir = 1;

void handler_t(void) {

  if(dim &#38;lt; counter){
    ledState = true;
  }
  else{
    ledState = false;
  }

  digitalWrite(5,ledState);
  digitalWrite(12,ledState);
  digitalWrite(14,ledState);
  digitalWrite(20,ledState);

  counter++;
  if(counter &#38;gt; 50) counter = 0;
}

void setup(void) {

  pinMode(5,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(14,OUTPUT);
  pinMode(20,OUTPUT);
  pinMode(BOARD_LED_PIN,OUTPUT);

  Timer2.setPrescaleFactor(1);
  Timer2.setOverflow(500); //1079);
  //Timer2.setCompare1(1);      // overflow might be small
  Timer2.attachCompare1Interrupt(handler_t);
  SerialUSB.println(&#38;quot;done setup&#38;quot;);

}

void loop(void) {
  if(millis() - myTimer &#38;gt; 15){
    myTimer = millis();
    toggleLED();
    dim = dim + dir;
    if(dim &#38;gt; 50 &#124;&#124; dim == 0) dir = dir * -1;
  }

}&#60;/code&#62;&#60;/pre&#62;</description>
		</item>
		<item>
			<title>gbulmer on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22267</link>
			<pubDate>Tue, 05 Feb 2013 08:56:24 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">22267@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;stephanschulz - &#60;em&#62;&#34;since i am new to maple i am not sure how to implement the hardware timer correctly; i.e. .setPeriod .setOverflow ...&#34;&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;So the documentation at &#60;a href=&#34;http://leaflabs.com/docs/lang/api/hardwaretimer.html#lang-hardwaretimer&#34; rel=&#34;nofollow&#34;&#62;http://leaflabs.com/docs/lang/api/hardwaretimer.html#lang-hardwaretimer&#60;/a&#62;&#60;br /&#62;
isn't sufficient?&#60;/p&#62;
&#60;p&#62;The wonderful thing about MCU-boards like Arduino and Maple, is the libraries enable you to do simple experiments. Only using the on-board LED and printing messages up the serial monitor, it is practical to learn quite a lot. It is pretty safe to use those, and there is no need for extra electronics.&#60;/p&#62;
&#60;p&#62;Also, you could find some examples of people asking for explanations by using the Search at the top right of every page. Search for setPeriod, setOverflow, etc&#60;/p&#62;
&#60;p&#62;As an example, their is &#60;a href=&#34;https://github.com/leaflabs/projects/tree/master/thx/thx_pwm&#34; rel=&#34;nofollow&#34;&#62;https://github.com/leaflabs/projects/tree/master/thx/thx_pwm&#60;/a&#62;&#60;br /&#62;
mentioned on thread &#60;a href=&#34;http://forums.leaflabs.com/topic.php?id=863&#34; rel=&#34;nofollow&#34;&#62;http://forums.leaflabs.com/topic.php?id=863&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;(Full Disclosure: I am not a member of LeafLabs staff)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>stephanschulz on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22254</link>
			<pubDate>Mon, 04 Feb 2013 20:39:41 +0000</pubDate>
			<dc:creator>stephanschulz</dc:creator>
			<guid isPermaLink="false">22254@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;since i am new to maple i am not sure how to implement the hardware timer correctly; i.e. .setPeriod .setOverflow ...&#60;/p&#62;
&#60;p&#62;i would greatly appreciate some example code.&#60;/p&#62;
&#60;p&#62;thanks a lot.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22248</link>
			<pubDate>Mon, 04 Feb 2013 19:43:54 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">22248@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;stephanschulz - &#60;em&#62;&#34;i am using the maple mini which only has 12 pwm pins.&#34;&#60;/em&#62;&#60;br /&#62;
Ooops, sorry.&#60;/p&#62;
&#60;p&#62;&#60;em&#62;&#34;your suggested code would it create flicker is i use the serial or other interrupt suff?&#34;&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;I am not sure what you mean by flicker. If you mean might there me extra PWM signal changes, which might visualy look like flicke (or be observed using an oscilloscope), then no, there would be no extra signal changes.&#60;/p&#62;
&#60;p&#62;If you mean might the number of PWM signal changes be correct, but the duration of a PWM signal might not be exactly what it would be if it were generated by a hardware timer (i.e. measured on an oscilloscope), that is often called 'jitter'.&#60;br /&#62;
Yes, depending on the priority of interrupts, signals may jitter. You may theoretically be able to control that on Maple, by changing interrupt priority, and hence may be able to order the interrupt priorities so the time sensitive signals do not jitter. However that adds an extra dimension of complexity which you might (reasonably:-) want to avoid.&#60;/p&#62;
&#60;p&#62;This is partly why I mentioned using DMA. Even using DMA to load data from SRAM into GPIO registers may have jitter, but it should be of the order of a few cycles, I guess much less than 100ns (even then, only when contending with the CPU for buses), and so smaller magnitude, than the potential scale of jitter caused by higher interrupt priorities, which is the duration of the interrupt service routine (i.e. maybe us). If the time slice of PWM is 4us, then less than 100ns is under 2.5%, and compared to the 1ms cycle for PWM is 0.01%.&#60;/p&#62;
&#60;p&#62;How accurate must the PWM duration be?&#60;/p&#62;
&#60;p&#62;&#60;em&#62;&#34;maybe there is a way to use one of the hardware timers???&#34;&#60;/em&#62;&#60;/p&#62;
&#60;p&#62;PWM &#60;strong&#62;is&#60;/strong&#62; generated by the hardware timers, so should I assume you are asking if PWM 'simulation' could be driven by a hardware timer?&#60;/p&#62;
&#60;p&#62;In their simple forms, approach 1, 2 and 3 (as posted in my response) are triggered by a hardware timer.&#60;br /&#62;
For 256 level PWM at 1ms cycle, the difference between 1 and 2 is whether you set the timer to trigger every 4us (option 2) , or on the next change of a PWM pin (option 1). As you only want 5 extra PWM pins (use one timer channel to trigger the interrupt service routine), setting the clock to trigger at the next actual pin change is much more efficient because that only generates 6 interrupts/msecond vs 256 interrupts/msecond. However, option 2 (256 'events'/millisecond) can be much more easily turned into a DMA driven mechanism, which needs no processor time at all once the array of bits to control the ports is set up, though it does contend for buses 256 times in every 72,000 cycles.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>ala42 on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22247</link>
			<pubDate>Mon, 04 Feb 2013 19:43:07 +0000</pubDate>
			<dc:creator>ala42</dc:creator>
			<guid isPermaLink="false">22247@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Which precision do you need on your PWM outputs ?
&#60;/p&#62;</description>
		</item>
		<item>
			<title>stephanschulz on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22245</link>
			<pubDate>Mon, 04 Feb 2013 17:05:12 +0000</pubDate>
			<dc:creator>stephanschulz</dc:creator>
			<guid isPermaLink="false">22245@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;thanks for the reply.&#60;/p&#62;
&#60;p&#62;i am using the maple mini which only has 12 pwm pins.&#60;/p&#62;
&#60;p&#62;your suggested code would it create flicker is i use the serial or other interrupt suff?&#60;/p&#62;
&#60;p&#62;thx&#60;/p&#62;
&#60;p&#62;maybe there is a way to use one of the hardware timers???
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22225</link>
			<pubDate>Sat, 02 Feb 2013 19:07:27 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">22225@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;stephanschulz - IIRC Maple has 15 hardware PWM pins, so writing code to generate PWM is less necessary than on the Arduino, which only has 6 PWM outputs.&#60;/p&#62;
&#60;p&#62;If you really only need 16 PWMs, and can use the Maples 15 hardware PWM pins, then the code example at that link:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  digitalWrite(13, HIGH);
  delayMicroseconds(100); // Approximately 10% duty cycle @ 1KHz
  digitalWrite(13, LOW);
  delayMicroseconds(1000 - 100);
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Would give the 16th.&#60;/p&#62;
&#60;p&#62;If this isn't enough PWM outputs, then you are going to have to write some more sophisticated code.&#60;/p&#62;
&#60;p&#62;How experienced are you at writing embedded C?&#60;br /&#62;
It might help you judge by reading the following approaches.&#60;/p&#62;
&#60;p&#62;If you want far more PWMs than there are PWM pins, then here are several basic techniques:&#60;/p&#62;
&#60;p&#62;1. Event-based simulation (&#60;a href=&#34;http://en.wikipedia.org/wiki/Discrete_event_simulation&#34; rel=&#34;nofollow&#34;&#62;http://en.wikipedia.org/wiki/Discrete_event_simulation&#60;/a&#62;)&#60;br /&#62;
If you imagine you have the schedule (time) when each PWM pin is going to change, sorted by increasing time, you can set an alarm to &#34;wake up&#34; on the next scheduled pin change. The &#34;alarm&#34; is triggered by a timer, set to go off at that pin-change time in the future, and the &#34;wake up&#34; is done by an interrupt service routine which toggles the pin(s) scheduled to change at that time.&#60;/p&#62;
&#60;p&#62;2. 'Continuous' simulation (&#60;a href=&#34;http://en.wikipedia.org/wiki/Continuous_simulation&#34; rel=&#34;nofollow&#34;&#62;http://en.wikipedia.org/wiki/Continuous_simulation&#60;/a&#62;)&#60;br /&#62;
Imagine the PWM resolution is like an Arduino (4us), with 256 'time slices' to make a 1ms cycle.&#60;br /&#62;
Declare an array of short int (16 bits), &#60;code&#62;pwmbits[256];&#60;/code&#62; where the nth bit controls the nth PWM pin.&#60;br /&#62;
Maintain the PWM pattern for all pins in that array, so &#60;code&#62;analogueWrite(7, 23);&#60;/code&#62; would set, say, the 7th bit of every entry in &#60;code&#62;pwmbits[]&#60;/code&#62;, in this case the first 23 array entries would have a 1 in bit position 7, and the other 233 (256-23) would be 0.&#60;br /&#62;
Copy a an element from &#60;code&#62;pwmbits[i];&#60;/code&#62; to a 16bit port every 4us. So all 16 pins of the port are outputting a PWM signal.&#60;br /&#62;
Edit. Copying pwmbits[i] to the GPIO port would be executed in an interrupt service routine, triggered by a timer.&#60;br /&#62;
Improvement 1, do the copying with a Maple DMA controller, so this all happens without any CPU (software) activity.&#60;br /&#62;
Improvement 2, maintain several arrays, one per 16 bit port, and use all of the pins as PWM pins.&#60;/p&#62;
&#60;p&#62;3 Combine the two techniques. IMHO this is tricky, and unlikely to give significant benefits.&#60;/p&#62;
&#60;p&#62;4. SPI is a shift register, so the data-out pin sends 8bits at a time as a serial bit stream. Feed 256 bits (&#60;code&#62;unsigned char bits[32];&#60;/code&#62;) into an SPI peripheral and it will generate a pulse train (and hence could do more things than simple PWM).&#60;br /&#62;
An &#60;code&#62;analogueWrite(pin, value);&#60;/code&#62; would set the 256 bits in &#60;code&#62;bits[]&#60;/code&#62; to have value 1s, and 256-value 0s.  Use an interrupt routine to feed a byte from &#60;code&#62;bits[]&#60;/code&#62; into the SPI peripheral. There are two SPI peripherals, so this gives 2 PWM pins.&#60;br /&#62;
Improvement 1.  use a DMA controller to transfer &#60;code&#62;bits[]&#60;/code&#62; into the SPI peripheral, hence their is no CPU (software) involvement once the equivalent of analogueWrite() has initialised the array&#60;/p&#62;
&#60;p&#62;(Full Disclosure: I am not a member of LeafLabs staff)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>stephanschulz on "manually implement PWM"</title>
			<link>http://forums.leaflabs.com/topic.php?id=10191#post-22208</link>
			<pubDate>Fri, 01 Feb 2013 15:29:26 +0000</pubDate>
			<dc:creator>stephanschulz</dc:creator>
			<guid isPermaLink="false">22208@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;i found this detailed tutorial on the arduino site about how to turn any digital pin in to a PWM pin&#60;/p&#62;
&#60;p&#62;&#60;a href=&#34;http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM&#34; rel=&#34;nofollow&#34;&#62;http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM&#60;/a&#62;&#60;/p&#62;
&#60;p&#62;i was wondering how one would do this on the maple.&#60;/p&#62;
&#60;p&#62;ideally i would need some sort of PWM control on 16 pins.&#60;/p&#62;
&#60;p&#62;thanks for any advice. stephan
&#60;/p&#62;</description>
		</item>

	</channel>
</rss>
