diff --git a/03_io_access/Makefile b/03_io_access/Makefile new file mode 100644 index 0000000..4fb5ac7 --- /dev/null +++ b/03_io_access/Makefile @@ -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 diff --git a/03_io_access/README.md b/03_io_access/README.md new file mode 100644 index 0000000..efc3305 --- /dev/null +++ b/03_io_access/README.md @@ -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 +``` diff --git a/03_io_access/lib/io.c b/03_io_access/lib/io.c new file mode 100644 index 0000000..8552713 --- /dev/null +++ b/03_io_access/lib/io.c @@ -0,0 +1,116 @@ +#include // For open() +#include // For libgpiod functions +#include // For perror() +#include // For atof() +#include // 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; +} diff --git a/03_io_access/lib/io.h b/03_io_access/lib/io.h new file mode 100644 index 0000000..27cfaaf --- /dev/null +++ b/03_io_access/lib/io.h @@ -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 diff --git a/03_io_access/src/main.c b/03_io_access/src/main.c new file mode 100644 index 0000000..e3c7d7e --- /dev/null +++ b/03_io_access/src/main.c @@ -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 // For sleep() +#include // 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; +} diff --git a/Makefile b/Makefile deleted file mode 100644 index 7c4bb4c..0000000 --- a/Makefile +++ /dev/null @@ -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) - diff --git a/README.md b/README.md index c783e96..2f87e24 100644 --- a/README.md +++ b/README.md @@ -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 ``` diff --git a/io.c b/io.c deleted file mode 100644 index d7d6a07..0000000 --- a/io.c +++ /dev/null @@ -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 -#include -#include // For sleep() -#include - - -#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; -}