Shop OBEX P1 Docs P2 Docs Learn Events
4 independant pwm channels — Parallax Forums

4 independant pwm channels

MauvaiMauvai Posts: 45
edited 2014-10-05 17:38 in Propeller 1
Looking to get 4 independent pwm channels running, preferably one core (even though I'm reasonably sure that's impossible. Checked the object exchange to find everything is in spin (which I don't speak), tried checking the servo lib, couldn't find what i was looking for. My solution was to launch a function into a new cog and run pwm from inside that cog, but it didn't work. Is there an easy way around this?

Code I tried:
/*
  Blink Light.c
  
  Blink light circuit connected to P26.
  
  http://learn.parallax.com/propeller-c-simple-circuits/blink-light
*/


#include "simpletools.h"                      // Include simpletools




void pwm2();


int main()                                    // main function
{
  
   unsigned int stack[40+40];
   //print("Hello");
   
   high(0);
   pause(500);
   low(0);
   pause(500);
   high(0);
   
   pwm_start(20000);
   pwm_set(26, 0, 10000);
   pwm_set(27, 1, 100);
   int i = 100;
   int j = 10000;
   cogstart(&pwm2, NULL, stack, sizeof(stack));
   //cogstart(&adder, NULL, stack, sizeof(stack));
  while(1)                                    // Endless loop
  {
   //print("loop start");
   pwm_set(26, 0, i);
   pwm_set(27, 1, 10000);
   i = i + 10;
   j = j + 10;
   
   if (i == 19000)
   {
     i = 100;
   } 
   if (j == 19000)
   {
     j = 100;
   }       
       
   pause(1);
  }
}




void pwm2()
{
  pause(250);
  pwm_start(20000);
   pwm_set(24, 0, 10000);
   pwm_set(25, 1, 100);
   int i = 100;
   int j = 10000;
  while(1)                                    // Endless loop
  {
   //print("loop start");
   pwm_set(24, 0, i);
   pwm_set(25, 1, j);
   i = i + 10;
   j = j + 10;
   
   if (i == 19000)
   {
     i = 100;
   } 
   if (j == 19000)
   {
     j = 100;
   }
 }          
}  

Comments

  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-10-04 17:34
    libpropeller has some great PWM objects (2-channel version and 32-channel). API documentation for libpropeller can be found here.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-10-04 17:37
    Mauvai wrote: »
    Checked the object exchange to find everything is in spin (which I don't speak)

    I found that odd too. There are a few C/C++ libraries floating around for the Propeller, but they seem to all reside on GitHub instead of in the OBEX (my library - PropWare - is on GitHub as well)
  • MauvaiMauvai Posts: 45
    edited 2014-10-05 05:55
    Thanks for that :)
    Can you provide a little clarification? Presumably if i need 4 pwm channels, i need the 32-channel version? Which bits do i need specifically?
    Can i download the h file and simply include it?
  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-10-05 08:15
    In general, you can determine a C or C++ file's dependencies by looking at the "#include" statements. For pwm32.h, it has two:
    • #include <stdint.h>
    • #include <propeller.h>
    As a Propeller-C[++] user, you'll quickly recognize that propeller.h is part of PropGCC, so that's already included. You can do the searching yourself, or just trust me when I say that stdint is part of PropGCC too :). In general, most anything that follows the "std*.h" pattern will be part of the "standard" library.
    What does that mean? That means no dependencies. When looking at a header file (*.h), make sure you also look for a source file (*.c or *.cpp or *.cxx) with a matching name. In this case, there is none - all code is contained within the header.

    So, it's real simple! Just grab pwm32.h and put it in your project folder :). You'll need to add "#include "pwm32.h" on top of any file that needs access to it.
    For examples on how to use it, I'd recommend poking through the PWM32 unit test or asking SRLM (the author). I can answer some basic questions about but have never used it myself.
  • MauvaiMauvai Posts: 45
    edited 2014-10-05 09:44
    Yes i gathered that much (thanks though) - i tried adding it to the project folder, and then added
    #include <pwm32.h>
    

    As I would with any C/C++ project - however when i tired to build this, without calling any functions from the file, I got the following error:


    ./pwm32.h:21:1: error: unknown type name 'namespace'
    ./pwm32.h:22:1: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
    Done. Build Failed!
  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-10-05 09:49
    All objects in libpropeller (and PropWare for that matter) are C++ not C objects. PropGCC determines a file's language based on the extension of the source file (Blink_Light.c), and therefore it's trying to compile pwm32.h as a C object - which isn't possible. Simply change Blink_Light.c to Blink_Light.cpp and that should do it.
  • MauvaiMauvai Posts: 45
    edited 2014-10-05 12:21
    Apologies for being of nuisance once again

    I got the code compiling by changing the compiler in the simple IDE to c++ - as the project is in a .h file, it cannot be changed to cpp so easily. I think.

    The code I am running is as follows:
    #include "simpletools.h"                      // Include simpletools#include "pwm32.h"
    
    
    void pwm2();
    
    
    
    
    using namespace libpropeller;
    
    
    int main()                                    // main function
    {
    
    
      
      PWM32 pwm1; //PWM32 constructor
      
      
      //Servo(int pin, int pulse_width) (pulse width in us)
      pwm1.Servo(24, 1);
      pwm1.Servo(25, 100);
      pwm1.Servo(26, 1000);
      pwm1.Servo(27, 1900);
    }
    
    The code compiles and runs, but doesn't do anything. My 4 LEDs sit there dark :-/
  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-10-05 12:36
    Not a nuisance :) don't worry. I'll give this a try locally and see what I can come up with.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-10-05 12:44
    PWM32 starts a new cog and that cog is not started until you call PWM32::Start(). So, simply add
    pwm1.Start()
    
    after the instantiation
  • MauvaiMauvai Posts: 45
    edited 2014-10-05 16:29
    Success! all is working correctly, thank you! As final request: if I desired to learn about the code at the top of the file, where would I go? Thank you :)
  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-10-05 17:15
    Mauvai wrote: »
    Success! all is working correctly, thank you! As final request: if I desired to learn about the code at the top of the file, where would I go? Thank you :)

    Glad to hear it!

    Assuming you're referring to this:






    #ifdef __GNUC__



    #define INLINE__ static inline



    #define Yield__() __asm__ volatile( "" ::: "memory" )



    #define PostEffect__(X, Y) __extension__({ int tmp__ = (X); (X) = (Y); tmp__; })



    #else



    #define INLINE__ static



    static int tmp__;



    #define PostEffect__(X, Y) (tmp__ = (X), (X) = (Y), tmp__)



    #define Yield__()



    #endif


    It's called preprocessor macros. What these macros do is beyond me. But #define just creates a variable that is, for all intents and purposes, copied and pasted later. So:
    #define add(x, y) (x + y)
    
    z = add(3, 4);
    

    would be turn into
    z = (3 + 4);
    

    before being compiled.
  • MauvaiMauvai Posts: 45
    edited 2014-10-05 17:38
    I was aware of define. More interested in the actual macros - The internal pwm function calls Yield__() - I was just curious as to how it worked, as there is little documentation on the inner workings of these files.
Sign In or Register to comment.