Pi IoT In C Using Linux Drivers - The PWM Driver
Written by Harry Fairhead   
Monday, 10 May 2021
Article Index
Pi IoT In C Using Linux Drivers - The PWM Driver
Simple PWM Functions
Complete PWM Program

 

In book, but not in this extract:

  • Controlling An LED
  • How Fast Can You Modulate?
  • Controlling a Servo
  • What Else Can You Use PWM For?

Complete PWM Program

This version of the program allows a variable number of parameters:

#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <stdarg.h>
FILE *doCommand(char *cmd)
{
    FILE *fp = popen(cmd, "r");
    if (fp == NULL)
    {
        printf("Failed to run command %s \n\r", cmd);
        exit(1);
    }
    return fp;
}
void checkPWM()
{
    FILE *fd = doCommand("sudo  dtparam -l");
    char output[1024];
    int txfound = 0;
    char indicator[] = "pwm-2chan";
    char command[] = "sudo dtoverlay pwm-2chan";
    while (fgets(output, sizeof(output), fd) != NULL)
    {
        printf("%s\n\r", output);
        fflush(stdout);
        if (strstr(output, indicator) != NULL)
        {
            txfound = 1;
        }
    }
    if (txfound == 0)
    {
        pclose(fd);
        fd = doCommand(command);
    }
    pclose(fd);
}
enum pwm
{
    OpenChan,
    SetFreq,
    SetDuty,
    EnableChan,
    DisableChan,
    CloseChan,
    InvertChan
};
int pwmAction(enum pwm action, int chan, ...)
{
    static int fdf[2];
    static int fdd[2];
    int fd;
    int param;
    char buf[150];
    char schan[2];
    va_list params;
    int status;
    int L;
    if (chan != 0 && chan != 1)
        return -1;
    snprintf(schan, 2, "%d", chan);
    switch (action)
    {
    case OpenChan:
        checkPWM();
        fd = open("/sys/class/pwm/pwmchip0/export",
O_WRONLY); if (fd < 0) printf("failed to open PWM Chip"); write(fd, schan, 1); close(fd); sleep(3); snprintf(buf, 150, "%s%s%s",
"/sys/class/pwm/pwmchip0/pwm",schan, "/period"); fdf[chan] = open(buf, O_WRONLY); if (fdf < 0) printf("failed to open period"); snprintf(buf, 150, "%s%s%s",
"/sys/class/pwm/pwmchip0/pwm",schan, "/duty_cycle"); fdd[chan] = open(buf, O_WRONLY); if (fdd < 0) printf("failed to open duty"); break; case SetFreq: va_start(params, chan); param = va_arg(params, int); L = snprintf(buf, 150, "%d", param); write(fdf[chan], buf, L); break; case SetDuty: va_start(params, chan); param = va_arg(params, int); L = snprintf(buf, 150, "%d", param); write(fdd[chan], buf, L); break; return 0; case EnableChan: snprintf(buf, 150, "%s%s%s",
"/sys/class/pwm/pwmchip0/pwm", schan, "/enable"); fd = open(buf, O_WRONLY); if (fd < 0) printf("failed to open enable"); write(fd, "1", 1); close(fd); break; case DisableChan: snprintf(buf, 150, "%s%s%s",
"/sys/class/pwm/pwmchip0/pwm",schan, "/enable"); fd = open(buf, O_WRONLY); write(fd, "0", 1); close(fd); break; case CloseChan: close(fdf[chan]); close(fdd[chan]); fd = open("/sys/class/pwm/pwmchip0/unexport",
O_WRONLY); write(fd, schan, 1); close(fd); break; case InvertChan: va_start(params, chan); param = va_arg(params, int); snprintf(buf, 150, "%s%s%s",
"/sys/class/pwm/pwmchip0/pwm",schan, "/polarity"); fd = open(buf, O_WRONLY); if (param == 0) { L = snprintf(buf, 150, "%s", "normal"); write(fd, buf, L); } if (param == 1) { L = snprintf(buf, 150, "%s", "inversed"); write(fd, buf, L); } close(fd); break; } return 0; } int main(int argc, char **argv) { pwmAction(OpenChan, 0); struct timespec delay = {0, 6667 * 2}; int t = 20 * 1000000; pwmAction(SetFreq, 0, t); int d1 = t * 2.5 / 100; int d2 = t * 12 / 100; pwmAction(InvertChan,0,1); pwmAction(EnableChan, 0); for (;;) { pwmAction(SetDuty, 0, d1); sleep(1); pwmAction(SetDuty, 0, d2); sleep(1); } }

Summary 

Italics indicates not covered in this extract

  • PWM, Pulse Width Modulation, has a fixed repetition rate but a variable duty cycle, i.e. the amount of time the signal is high or low changes.

  • PWM can be generated by software simply by changing the state of a GPIO line correctly, but it can also be generated in hardware, so relieving the processor of some work.

  • Hardware PWM can generate high speed pulses, but how quickly you can change the duty cycle is still software-limited.

  • All versions of the Pi have two hardware PWM channels which can be used and configured using Linux drivers.

  • The PWM drivers do not provide control over the PWM clock frequency which determines how accurately you can set the duty cycle.

  • A typical use of PWM is to control a servo and this only requires a PWM frequency of 50Hz. The position of the servo depends on the duty cycle.

  • You can easily invert the sense of the PWM signal, which is useful when the device is being driven by a single transistor.

  • As well as being a way of signaling, PWM can also be used to vary the amount of power or voltage transferred. The higher the duty cycle, the more power/voltage.

  • In the same way, by varying the duty cycle, you can dim an LED. As the brightness of an LED is not linear with applied voltage, you have to modify the output using a cubic law to get linear changes in brightness.

 

Raspberry Pi IoT In C Using Linux Drivers

By Harry Fairhead

Cdrivers360

Buy from Amazon.

Contents

  1.  Choosing A Pi For IoT

  2. C and Visual Studio Code

  3.  Drivers: A First Program

  4.  The GPIO Character Driver
         Extract: GPIO Character Driver

  5. GPIO Using I/O Control

  6.  GPIO Events

  7.  The Device Tree
        Extract: The DHT22

  8.  Some Electronics

  9.  Pulse Width Modulation
    Extract:  The PWM Driver 

  10. SPI Devices
    Extract: The SPI Driver 

  11. I2C Basics

  12. The I2C Linux Driver ***NEW!

     

  13. Advanced I2C

  14. Sensor Drivers – Linux IIO & Hwmon
      Extract: Hwmon  

  15. 1-Wire Bus
      Extract: 1-Wire And The DS18B20 

  16. Going Further With Drivers

  17. Appendix I

 <ASIN:1871962641>

<ASIN:B08W9V7TP9>

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


TestSprite Announces End-to-End QA Tool
14/11/2024

TestSprite has announced an early access beta program for its end-to-end QA tool, along with $1.5 million pre-seed funding aimed at accelerating product development, expanding the team, and scaling op [ ... ]



Random Gifts For Programmers
24/11/2024

Not really random. Not even pseudo random, more stuff that caught my attention and that I, for one, would like to be given. And, yes, if I'm not given them, I'd probably buy some for myself.


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info


<ASIN:1871962609>

 <ASIN:1871962617>

<ASIN:1871962455>

<ASIN:1871962463>



Last Updated ( Wednesday, 12 May 2021 )