Page 8 of 14
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);
}
}