Article Index

 

Page 133

#define _GNU_SOURCE
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

void pwm(struct gpiod_line *line, int);

int main(int argc, char **argv)
{
    int period = 20;
    int duty = 25;
    int res;
    struct gpiod_chip *chip = gpiod_chip_open_by_number(0);
    struct gpiod_line *line4 = gpiod_chip_get_line(chip, 4);
    res = gpiod_line_request_output(line4, "test output", 0);

    struct timespec ontime = {0, 0};
    struct timespec offtime = {0, 0};
    ontime.tv_nsec = period * duty * 10 * 1000;
    offtime.tv_nsec = (period - period * duty / 100) * 1000 * 1000;

    for (;;)
    {
        res = gpiod_line_set_value(line4, 1);
        nanosleep(&ontime, NULL);
        res = gpiod_line_set_value(line4, 0);
        nanosleep(&offtime, NULL);
    };
}
 

Remember to change "0" to "4" if you are running on a Pi 5.

Page  134

#define _GNU_SOURCE
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

struct pwmargs
{
    struct gpiod_line *line;
    struct timespec ontime;
    struct timespec offtime;
};

void *pwmrun(void *arg)
{
    struct pwmargs *pwmdata = (struct pwmargs *)arg;
    int res;
    for (;;)
    {
        res = gpiod_line_set_value(pwmdata->line, 1);
        nanosleep(&(pwmdata->ontime), NULL);
        res = gpiod_line_set_value(pwmdata->line, 0);
        nanosleep(&(pwmdata->offtime), NULL);
    };
}

int pwm(struct gpiod_line *line, int period, int duty)
{
    static struct pwmargs pwmdata;
    pwmdata.line = line;
    pwmdata.ontime.tv_sec = 0;
    pwmdata.ontime.tv_nsec = period * duty * 10;
    pwmdata.offtime.tv_sec = 0;
    pwmdata.offtime.tv_nsec = (period - period * duty / 100) * 1000;

    pthread_t pwmThread;
    if (pthread_create(&pwmThread, NULL, pwmrun, (void *)&pwmdata))
    {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }
    return 0;
};

int main(int argc, char **argv)
{
    int res;
    struct gpiod_chip *chip = gpiod_chip_open_by_number(0);
    struct gpiod_line *line4 = gpiod_chip_get_line(chip, 4);
    res = gpiod_line_request_output(line4, "test output", 0);

    pwm(line4, 20 * 1000, 25);
    for (;;)
    {
    };
}
 

Remember to change "0" to "4" if you are running on a Pi 5.

Page 137

#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <fcntl.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)
    {
        fd = doCommand(command);
        sleep(2);
    }

    pclose(fd);
}

int main(int argc, char **argv)
{
    checkPWM();

    int fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY);
    write(fd, "0", 1);
    close(fd);
    sleep(2);
    fd = open("/sys/class/pwm/pwmchip0/pwm0/period", O_WRONLY);
    write(fd, "10000000", 8);
    close(fd);
    fd = open("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", O_WRONLY);
    write(fd, "8000000", 7);
    close(fd);
    fd = open("/sys/class/pwm/pwmchip0/pwm0/enable", O_WRONLY);
    write(fd, "1", 1);
    close(fd);
}

 

Remember to change "0" to "4" if you are running on a Pi 5.

Page 139

#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <fcntl.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";
    char command[] = "sudo dtoverlay pwm-2chan, pin=18 func=2 pin2=12 func2=4" ;
    while (fgets(output, sizeof(output), fd) != NULL)
    {
        printf("%s\n\r", output);
        fflush(stdout);
        if (strstr(output, indicator) != NULL)
        {
            txfound = 1;
            printf("Overlay already loaded\n\r");
        }
    }
    if (txfound == 0)
    {
        fd = doCommand(command);
        sleep(2);
    }

    pclose(fd);
}

int main(int argc, char **argv)
{
    checkPWM();  
    int fd = open("/sys/class/pwm/pwmchip2/export", O_WRONLY);
    write(fd, "0", 1);
    close(fd);
    sleep(2);
    fd = open("/sys/class/pwm/pwmchip2/pwm0/period", O_WRONLY);
    write(fd, "10000001", 8);
    close(fd);
    fd = open("/sys/class/pwm/pwmchip2/pwm0/duty_cycle", O_WRONLY);
    write(fd, "4000000", 7);
    close(fd);
    fd = open("/sys/class/pwm/pwmchip2/pwm0/enable", O_WRONLY);
    write(fd, "1", 1);
    close(fd);
   
    fd = open("/sys/class/pwm/pwmchip2/export", O_WRONLY);
    write(fd, "2", 1);
    close(fd);
    sleep(2);
    fd = open("/sys/class/pwm/pwmchip2/pwm2/period", O_WRONLY);
    write(fd, "10000001", 8);
    close(fd);
    fd = open("/sys/class/pwm/pwmchip2/pwm2/duty_cycle", O_WRONLY);
    write(fd, "5000000", 7);
    close(fd);
    fd = open("/sys/class/pwm/pwmchip2/pwm2/enable", O_WRONLY);
    write(fd, "1", 1);
    close(fd);
}
 

Page 141 - full listing of finished program on Page 155

#define _DEFAULT_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdarg.h>

 #define Pi5

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 pin=12 func=4 pin2=13 func2=4";
    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;
    char buf[150];
    char schan[6];
    va_list params;
    int param;

    if (chan != 0 && chan != 1)
        return -1;

#if defined(Pi5)
    char path[] = "/sys/class/pwm/pwmchip2/";
#else
    char path[] = "/sys/class/pwm/pwmchip0/";
#endif
    char chanNum[2];
    snprintf(schan, 6, "%s%d", "pwm", chan);
    snprintf(chanNum, 2, "%d", chan);

    int L;

    switch (action)
    {
    case OpenChan:
        checkPWM();
        snprintf(buf, 150, "%s%s", path, "export");
        fd = open(buf, O_WRONLY);
        write(fd, chanNum, 1);
        close(fd);
        sleep(2);
        snprintf(buf, 150, "%s%s%s", path, schan, "/period");
        fdf[chan] = open(buf, O_WRONLY);
        snprintf(buf, 150, "%s%s%s", path, schan, "/duty_cycle");
        fdd[chan] = open(buf, O_WRONLY);
        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;
    case EnableChan:
        snprintf(buf, 150, "%s%s%s", path, schan, "/enable");
        fd = open(buf, O_WRONLY);
        write(fd, "1", 1);
        close(fd);
        break;
    case DisableChan:
        snprintf(buf, 150, "%s%s%s", path, schan, "/enable");
        fd = open(buf, O_WRONLY);
        write(fd, "0", 1);
        close(fd);
        break;
    case CloseChan:
        close(fdf[chan]);
        close(fdd[chan]);
        snprintf(buf, 150, "%s%s%s", path, "/unexport");
        printf("%s\n", buf);
        fd = open(buf, O_WRONLY);
        write(fd, chanNum, 1);
        close(fd);
        break;

    case InvertChan:
        va_start(params, chan);
        param = va_arg(params, int);
        snprintf(buf, 150, "%s%s%s", path, 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, 0);
   

    int t = 20 * 1000000;
    pwmAction(SetFreq, 0, t);
    int d1 = t * 2.5 / 100;
    int d2 = t * 12 / 100;
   
    pwmAction(EnableChan, 0, 0);

    for (;;)
    {
        pwmAction(SetDuty, 0, d1);
        sleep(1);
        pwmAction(SetDuty, 0, d2);
        sleep(1);
    }
}