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. This repo contains my code for the Distributed Embedded Systems course at the University of Rostock.
```bash ```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;
}