io: refactor
This commit is contained in:
parent
782252e0bd
commit
c452d42213
|
|
@ -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
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
15
Makefile
15
Makefile
|
|
@ -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)
|
||||
|
||||
|
|
@ -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
129
io.c
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue