io: refactor

This commit is contained in:
Daniel Meiburg 2024-05-15 00:37:25 +02:00
parent 782252e0bd
commit c452d42213
Signed by: dm
GPG Key ID: E5827ECFFE0AA4F2
8 changed files with 218 additions and 145 deletions

39
03_io_access/Makefile Normal file
View File

@ -0,0 +1,39 @@
CC = gcc
CFLAGS = -Wall -Ilib
LDFLAGS = -lgpiod
# Directories
SRCDIR = src
LIBDIR = lib
OBJDIR = obj
# Source files
LIB_SOURCES = $(wildcard $(LIBDIR)/*.c)
SRC_SOURCES = $(wildcard $(SRCDIR)/*.c)
# Object files
LIB_OBJECTS = $(LIB_SOURCES:$(LIBDIR)/%.c=$(OBJDIR)/%.o)
SRC_OBJECTS = $(SRC_SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
# Target executable
TARGET = io
# Create obj directory if it doesn't exist
$(shell mkdir -p $(OBJDIR))
# Rules
all: $(TARGET)
$(TARGET): $(LIB_OBJECTS) $(SRC_OBJECTS)
$(CC) $(LIB_OBJECTS) $(SRC_OBJECTS) -o $@ $(LDFLAGS)
$(OBJDIR)/%.o: $(LIBDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJDIR)/*.o $(TARGET)
.PHONY: all clean

11
03_io_access/README.md Normal file
View File

@ -0,0 +1,11 @@
# IO Access
This program demonstrates how to access the GPIO pins on the Raspberry Pi using
a LED, a button and a temperature sensor.
## Usage
```bash
$ make
$ ./io
```

116
03_io_access/lib/io.c Normal file
View File

@ -0,0 +1,116 @@
#include <fcntl.h> // For open()
#include <gpiod.h> // For libgpiod functions
#include <stdio.h> // For perror()
#include <stdlib.h> // For atof()
#include <unistd.h> // For close()
#include "io.h"
// Global variables for GPIO chip and lines
static struct gpiod_chip *chip = NULL;
static struct gpiod_line *led_line = NULL;
static struct gpiod_line *button_line = NULL;
// Error handling function
static int handle_error(const char *msg) {
perror(msg);
return -1;
}
// Helper function to initialize a GPIO line
static struct gpiod_line* init_gpio_line(int pin, const char *consumer, int direction) {
struct gpiod_line *line = gpiod_chip_get_line(chip, pin);
if (!line) {
handle_error("Failed to get GPIO line");
return NULL;
}
int request_result;
if (direction == GPIOD_LINE_DIRECTION_OUTPUT) {
request_result = gpiod_line_request_output(line, consumer, 0);
} else {
request_result = gpiod_line_request_input(line, consumer);
}
if (request_result < 0) {
handle_error("Failed to request GPIO line");
return NULL;
}
return line;
}
// Initialize GPIO chip and lines
// Call cleanup_gpio() to release resources
int initialize_gpio(const char *chip_name, int led_pin, int button_pin) {
chip = gpiod_chip_open_by_name(chip_name);
if (!chip) return handle_error("Failed to open GPIO chip");
led_line = init_gpio_line(led_pin, "gpio-led", GPIOD_LINE_DIRECTION_OUTPUT);
if (!led_line) return -1;
button_line = init_gpio_line(button_pin, "gpio-button", GPIOD_LINE_DIRECTION_INPUT);
if (!button_line) return -1;
return 0;
}
// Set LED state
void set_led_state(int state) {
if (led_line) {
gpiod_line_set_value(led_line, state);
}
}
// Read button state
int read_button_state() {
if (button_line) {
return gpiod_line_get_value(button_line);
}
return -1; // Return an error if button_line is not initialized
}
// Cleanup GPIO resources
void cleanup_gpio() {
if (led_line) {
gpiod_line_release(led_line);
led_line = NULL;
}
if (button_line) {
gpiod_line_release(button_line);
button_line = NULL;
}
if (chip) {
gpiod_chip_close(chip);
chip = NULL;
}
}
// Error handling function for temperature reading
static float handle_temp_error(const char *msg) {
perror(msg);
return -1.0;
}
// Read temperature from sensor
float read_temperature(const char *sensor_path) {
int fd;
float temperature;
char buf[16]; // Large enough to hold the temperature string
fd = open(sensor_path, O_RDONLY);
if (fd == -1) {
return handle_temp_error("Failed to open temperature file");
}
ssize_t numRead = read(fd, buf, sizeof(buf) - 1);
if (numRead == -1) {
close(fd);
return handle_temp_error("Failed to read temperature file");
}
buf[numRead] = '\0'; // Null-terminate the string
temperature = atof(buf) / 1000.0; // Convert the string to a float
close(fd);
return temperature;
}

19
03_io_access/lib/io.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef IO_LIB_H
#define IO_LIB_H
// Function to initialize the GPIO chip, LED line, and Button line
int initialize_gpio(const char *chip_name, int led_pin, int button_pin);
// Function to set the LED state
void set_led_state(int state);
// Function to read the Button state
int read_button_state();
// Function to cleanup the GPIO chip, LED line, and Button line
void cleanup_gpio();
// Function to read the temperature from a sensor
float read_temperature(const char *sensor_path);
#endif // LIB_H

31
03_io_access/src/main.c Normal file
View File

@ -0,0 +1,31 @@
// This document implements some function to interact with an
// Raspberry Pi 4 and some external components.
// Used components: DS18B20, and LED and a push button.
// libgpiod is used for the communication with the GPIOs
#include <unistd.h> // For sleep()
#include <stdio.h> // For printf()
#include "io.h"
#define GPIO_CHIP "gpiochip0"
#define LED_GPIO_PIN 18
#define BUTTON_GPIO_PIN 22
#define LED_BLINK_TIME 1 // Blink delay in seconds
#define SENSOR_PATH "/sys/bus/w1/devices/28-000000306565/temperature" // DS18B20 sensor address
int main(void) {
if (initialize_gpio(GPIO_CHIP, LED_GPIO_PIN, BUTTON_GPIO_PIN) < 0) {
return 1;
}
for (int i = 0; i < 10; i++) { // Blink the LED 10 times for demonstration
set_led_state(1); // Turn the LED on
sleep(LED_BLINK_TIME);
set_led_state(0); // Turn the LED off
sleep(LED_BLINK_TIME);
printf("Button state: %d\n", read_button_state());
printf("Temperature: %.2f\n", read_temperature(SENSOR_PATH));
}
cleanup_gpio();
return 0;
}

View File

@ -1,15 +0,0 @@
CC=gcc
CFLAGS=-lgpiod
TARGET=io
all: $(TARGET)
$(TARGET): io.c
$(CC) -o $(TARGET) io.c $(CFLAGS)
run:
./$(TARGET)
clean:
rm -f $(TARGET)

View File

@ -3,5 +3,6 @@
This repo contains my code for the Distributed Embedded Systems course at the University of Rostock.
```bash
gcc -o io io.c -lgpiod && ./io
make
./io
```

129
io.c
View File

@ -1,129 +0,0 @@
// This document implements some function to interact with an
// Raspberry Pi 4 and some external components.
// Used components: DS18B20, and LED and a push button.
// libgpiod is used for the communication with the GPIOs
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h> // For sleep()
#include <fcntl.h>
#define GPIO_CHIP "gpiochip0"
#define LED_GPIO_PIN 18
#define BUTTON_GPIO_PIN 22
#define LED_BLINK_TIME 1 // Blink delay in seconds
#define SENSOR_PATH "/sys/bus/w1/devices/28-000000306565/temperature" // DS18B20 sensor address
// function to set the LED state by passing the pin and state
void set_led(int pin, int state) {
struct gpiod_chip *chip;
struct gpiod_line *line;
chip = gpiod_chip_open_by_name(GPIO_CHIP);
if (!chip) {
perror("Failed to open GPIO chip");
return;
}
line = gpiod_chip_get_line(chip, pin);
if (!line) {
perror("Failed to get GPIO line");
gpiod_chip_close(chip);
return;
}
if (gpiod_line_request_output(line, "gpio-led", 0) < 0) {
perror("Failed to request line as output");
gpiod_chip_close(chip);
return;
}
// Set the LED state
gpiod_line_set_value(line, state);
// Release the GPIO line and chip
gpiod_line_release(line);
gpiod_chip_close(chip);
}
// function to blink the LED by passing the pin, number of blinks and the delay
void blink_led(int pin, int time, int delay) {
for (int i = 0; i < time; i++) {
set_led(pin, 1);
sleep(delay);
set_led(pin, 0);
sleep(delay);
}
}
float read_temperature() {
int fd;
float temperature;
char buf[16]; // Large enough to hold the temperature string
fd = open(SENSOR_PATH, O_RDONLY);
if (fd == -1) {
perror("Failed to open temperature file");
return -1; // Return an error indicator
}
ssize_t numRead = read(fd, buf, sizeof(buf) - 1);
if (numRead == -1) {
perror("Failed to read temperature file");
close(fd);
return -1; // Return an error indicator
}
buf[numRead] = '\0'; // Null-terminate the string
temperature = atof(buf) / 1000; // Convert the string to an integer
close(fd);
return temperature;
}
// funciton to read button status
int read_button(int pin) {
struct gpiod_chip *chip;
struct gpiod_line *line;
int value;
chip = gpiod_chip_open_by_name(GPIO_CHIP);
if (!chip) {
perror("Failed to open GPIO chip");
return -1;
}
line = gpiod_chip_get_line(chip, pin);
if (!line) {
perror("Failed to get GPIO line");
gpiod_chip_close(chip);
return -1;
}
if (gpiod_line_request_input(line, "gpio-button") < 0) {
perror("Failed to request line as input");
gpiod_chip_close(chip);
return -1;
}
value = gpiod_line_get_value(line);
// Release the GPIO line and chip
gpiod_line_release(line);
gpiod_chip_close(chip);
return value;
}
int main(void) {
// printf("Temperature: %.2f\n", read_temperature(SENSOR_ADDRESS));
// blink_led(LED_GPIO_PIN, 5, LED_BLINK_TIME);
// printf("Temperature: %.2f\n", read_temperature());
// check button status and sleep for a second
while(1){
printf("Button status: %d\n", read_button(BUTTON_GPIO_PIN));
sleep(1);
}
return 0;
}