From 0eb11d9fc6790c0a66de024b3ee03e8699c4995d Mon Sep 17 00:00:00 2001 From: Geoffrey Frogeye Date: Sun, 29 Apr 2018 21:57:29 +0200 Subject: [PATCH] Added I2C (SRF05 & LCD) --- chef/Makefile | 2 +- chef/src/i2c.c | 55 +++++++++++++++ chef/src/i2c.h | 17 +++++ chef/src/lcd.c | 68 +++++++++++++++++++ chef/src/lcd.h | 31 +++++++++ chef/src/srf08.c | 44 ++++++++++++ chef/src/srf08.h | 33 +++++++++ chef/src/testI2c.c | 50 ++++++++++++++ .../robotech/cdfprincipal/busybox-extra.conf | 1 + .../board/robotech/cdfprincipal/post-image.sh | 10 +++ .../rootfs_overlay/etc/init.d/S30hardware | 8 ++- raspberrypi/configs/cdfprincipal_defconfig | 15 ++-- 12 files changed, 326 insertions(+), 8 deletions(-) create mode 100644 chef/src/i2c.c create mode 100644 chef/src/i2c.h create mode 100644 chef/src/lcd.c create mode 100644 chef/src/lcd.h create mode 100644 chef/src/srf08.c create mode 100644 chef/src/srf08.h create mode 100644 chef/src/testI2c.c create mode 100644 raspberrypi/board/robotech/cdfprincipal/busybox-extra.conf create mode 100755 raspberrypi/board/robotech/cdfprincipal/post-image.sh diff --git a/chef/Makefile b/chef/Makefile index 0a9e5b3..9347001 100644 --- a/chef/Makefile +++ b/chef/Makefile @@ -34,7 +34,7 @@ endif # RÈGLES DE COMPILATION # Règle éxecutée par défaut (quand on fait juste `make`) -default: bin/testpin bin/premier bin/local bin/testI2c bin/testLCD +default: bin/testpin bin/premier bin/local bin/testI2c # Binaires (dont il faut spécifier les objets explicitement) bin/premier: obj/CF.o obj/movement.o obj/debug.o obj/position.o diff --git a/chef/src/i2c.c b/chef/src/i2c.c new file mode 100644 index 0000000..9bf4216 --- /dev/null +++ b/chef/src/i2c.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include + +#include "i2c.h" + +pthread_mutex_t sI2C; + +void initI2C() +{ + pthread_mutex_init(&sI2C, NULL); +} + +int openI2C(int8_t address) +{ + lockI2C(); + int fd = wiringPiI2CSetup(address); + unlockI2C(); + if (fd < 0) { + perror("wiringPiI2CSetup"); + exit(EXIT_FAILURE); + } + return fd; +} + +int8_t readI2C(int fd, int8_t reg) +{ + lockI2C(); + int8_t res = wiringPiI2CReadReg8(fd, reg); + unlockI2C(); + return res; +} + +void writeI2C(int fd, int8_t reg, int8_t data) +{ + + lockI2C(); + int res = wiringPiI2CWriteReg8(fd, reg, data); + unlockI2C(); + if (res < 0) { + perror("wiringPiI2CWriteReg8"); + exit(EXIT_FAILURE); + } +} + +void lockI2C() +{ + pthread_mutex_lock(&sI2C); +} + +void unlockI2C() +{ + pthread_mutex_unlock(&sI2C); +} diff --git a/chef/src/i2c.h b/chef/src/i2c.h new file mode 100644 index 0000000..b5b90be --- /dev/null +++ b/chef/src/i2c.h @@ -0,0 +1,17 @@ +#ifndef __I2C_H__ +#define __I2C_H__ + +#include + +void initI2C(); +int openI2C(int8_t address); +int8_t readI2C(int fd, int8_t reg); +void writeI2C(int fd, int8_t reg, int8_t data); + +// Get full control over the I2C communication +// Note: Don't use methods from this library +// while in this mode +void lockI2C(); +void unlockI2C(); + +#endif diff --git a/chef/src/lcd.c b/chef/src/lcd.c new file mode 100644 index 0000000..a852866 --- /dev/null +++ b/chef/src/lcd.c @@ -0,0 +1,68 @@ +#include "lcd.h" +#include "i2c.h" +#include +#include + +int lcdFd; + +void initLCD() +{ + lcdFd = openI2C(LCD_ADDR); + + // TODO More details + sendLCD(0x33, LCD_MODE_CMD); // Initialise + sendLCD(0x32, LCD_MODE_CMD); // Initialise + sendLCD(0x06, LCD_MODE_CMD); // Cursor move direction + sendLCD(0x0C, LCD_MODE_CMD); // Blink Off + sendLCD(0x28, LCD_MODE_CMD); // Data length, number of lines, font size + sendLCD(0x01, LCD_MODE_CMD); // Clear display + delayMicroseconds(500); +} + +void clearLCD() +{ + sendLCD(0x01, LCD_MODE_CMD); + sendLCD(0x02, LCD_MODE_CMD); +} + +void gotoLCD(uint8_t line) +{ + sendLCD(line, LCD_MODE_CMD); +} + +void charLCD(char c) +{ + sendLCD(c, LCD_MODE_CHR); +} + +void printLCD(char* s) +{ + while (*s != '\0') { + charLCD(*s); + s++; + } +} + + +void sendLCD(uint8_t bits, uint8_t mode) +{ + lockI2C(); + // High bits + uint8_t part = mode | (bits & 0xF0) | LCD_BACKLIGHT; + wiringPiI2CReadReg8(lcdFd, part); + toggleEnableLCD(part); + + // Low bits + part = mode | ((bits << 4) & 0xF0) | LCD_BACKLIGHT; + wiringPiI2CReadReg8(lcdFd, part); + toggleEnableLCD(part); + unlockI2C(); +} + +void toggleEnableLCD(uint8_t bits) +{ + wiringPiI2CReadReg8(lcdFd, (bits | LCD_MASK_ENABLE)); + delayMicroseconds(1); + wiringPiI2CReadReg8(lcdFd, (bits & ~LCD_MASK_ENABLE)); + delayMicroseconds(50); +} diff --git a/chef/src/lcd.h b/chef/src/lcd.h new file mode 100644 index 0000000..27073a8 --- /dev/null +++ b/chef/src/lcd.h @@ -0,0 +1,31 @@ +#ifndef __LCD_H_ +#define __LCD_H_ + +#include "stdint.h" + +#define LCD_ADDR 0x27 + +#define LCD_MODE_CHR 1 +#define LCD_MODE_CMD 0 + +#define LCD_LINE_1 0x80 // 1st line +#define LCD_LINE_2 0xC0 // 2nd line + +#define LCD_BACKLIGHT_ON 0x08 +#define LCD_BACKLIGHT_OFF 0x08 +#define LCD_BACKLIGHT LCD_BACKLIGHT_ON + +#define LCD_MASK_ENABLE 0x04 // Enable bit + +// Public +void initLCD(); +void clearLCD(); +void gotoLCD(uint8_t line); +void charLCD(char c); +void printLCD(char* s); + +// Private +void sendLCD(uint8_t bits, uint8_t mode); +void toggleEnableLCD(uint8_t bits); + +#endif diff --git a/chef/src/srf08.c b/chef/src/srf08.c new file mode 100644 index 0000000..eb41c3e --- /dev/null +++ b/chef/src/srf08.c @@ -0,0 +1,44 @@ +#include + +#include "i2c.h" +#include "srf08.h" + +int openSRF08(int address) +{ + int fd = openI2C(address); + writeI2C(fd, SRF08_REGISTER_WRITE_MAX_GAIN, SRF08_DEFAULT_MAX_GAIN); + writeI2C(fd, SRF08_REGISTER_WRITE_RANGE, SRF08_DEFAULT_RANGE); + return fd; +} + +uint8_t revSRF08(int fd) +{ + return readI2C(fd, SRF08_REGISTER_READ_REVISION); +} + +void startSRF08(int fd) +{ + writeI2C(fd, SRF08_REGISTER_WRITE_COMMAND, SRF08_COMMAND_RANGING_US); +} + +void waitSRF08(int fd) +{ + while (revSRF08(fd) == 0xFF) { + sleep(0); + } +} + +float getSRF08(int fd) +{ + int8_t high = readI2C(fd, SRF08_REGISTER_READ_ECHO_1_HIGH) - SRF08_VALUES_OFFSET; + int8_t low = readI2C(fd, SRF08_REGISTER_READ_ECHO_1_LOW) - SRF08_VALUES_OFFSET; + int total = high * SRF08_VALUES_OFFSET + low; + return total * SOUNDSPEED_MM_P_US; +} + +float readSRF08(int fd) +{ + startSRF08(fd); + waitSRF08(fd); + return getSRF08(fd); +} diff --git a/chef/src/srf08.h b/chef/src/srf08.h new file mode 100644 index 0000000..ddf158e --- /dev/null +++ b/chef/src/srf08.h @@ -0,0 +1,33 @@ +#ifndef __SRF08_H__ +#define __SRF08_H__ + +#include + +int openSRF08(int address); +uint8_t revSRF08(int fd); +void startSRF08(int fd); +void waitSRF08(int fd); +// In mm +float getSRF08(int fd); +float readSRF08(int fd); + +#define SRF08_REGISTER_READ_REVISION 0x00 +#define SRF08_REGISTER_READ_ECHO_1_HIGH 0x02 +#define SRF08_REGISTER_READ_ECHO_1_LOW 0x03 + +#define SRF08_REGISTER_WRITE_COMMAND 0x00 +#define SRF08_REGISTER_WRITE_MAX_GAIN 0x01 +#define SRF08_REGISTER_WRITE_RANGE 0x02 + +#define SRF08_COMMAND_RANGING_IN 0x50 +#define SRF08_COMMAND_RANGING_CM 0x51 +#define SRF08_COMMAND_RANGING_US 0x52 + +#define SRF08_DEFAULT_MAX_GAIN 0x1F +#define SRF08_DEFAULT_RANGE 0xFF + +#define SRF08_VALUES_OFFSET 0x80 + +#define SOUNDSPEED_MM_P_US 0.3312 + +#endif diff --git a/chef/src/testI2c.c b/chef/src/testI2c.c new file mode 100644 index 0000000..59cbef1 --- /dev/null +++ b/chef/src/testI2c.c @@ -0,0 +1,50 @@ +/* Teste si une broche est connecté à une autre */ + +#include +#include +#include +#include +#include + +#include "srf08.h" +#include "i2c.h" +#include "lcd.h" + +int main(int argc, char* argv[]) +{ + + (void)argc; + (void)argv; + + initI2C(); + + // Adresse du SRF05 + uint8_t address = atoi(argv[1]); + + printf("Connecting to %d (0x%x)\n", address, address); + + initLCD(); + clearLCD(); + gotoLCD(LCD_LINE_1); + printLCD("Distance"); + + int front = openSRF08(address); + + char line[16]; + float l = 0; + for (;;) { + startSRF08(front); + + gotoLCD(LCD_LINE_2); + printf("l = %3f\n", l); + sprintf(line, "%f mm", l); + printLCD(line); + printLCD(" "); + + waitSRF08(front); + l = getSRF08(front); + + } + + +} diff --git a/raspberrypi/board/robotech/cdfprincipal/busybox-extra.conf b/raspberrypi/board/robotech/cdfprincipal/busybox-extra.conf new file mode 100644 index 0000000..7b1777d --- /dev/null +++ b/raspberrypi/board/robotech/cdfprincipal/busybox-extra.conf @@ -0,0 +1 @@ +CONFIG_RX=y diff --git a/raspberrypi/board/robotech/cdfprincipal/post-image.sh b/raspberrypi/board/robotech/cdfprincipal/post-image.sh new file mode 100755 index 0000000..5342cce --- /dev/null +++ b/raspberrypi/board/robotech/cdfprincipal/post-image.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +>> "${BINARIES_DIR}/rpi-firmware/config.txt" + cat << __EOF__ >> "${BINARIES_DIR}/rpi-firmware/config.txt" + +# activates I2C connectivity +dtparam=i2c_arm=on,i2c_arm_baudrate=1000000 +__EOF__ + + diff --git a/raspberrypi/board/robotech/cdfprincipal/rootfs_overlay/etc/init.d/S30hardware b/raspberrypi/board/robotech/cdfprincipal/rootfs_overlay/etc/init.d/S30hardware index 6999dc0..dfecd05 100755 --- a/raspberrypi/board/robotech/cdfprincipal/rootfs_overlay/etc/init.d/S30hardware +++ b/raspberrypi/board/robotech/cdfprincipal/rootfs_overlay/etc/init.d/S30hardware @@ -5,13 +5,17 @@ start() { printf "Starting hardware handling: " - modprobe pl2303 # USB↔Serial cable + modprobe pl2303 # USB↔Serial cable + modprobe i2c-bcm2708 # I2C + modprobe i2c-dev # I2C echo "OK" } stop() { printf "Stopping hardware handling: " - rmmod pl2303 # USB↔Serial cable + rmmod i2c-dev # I2C + rmmod i2c-bcm2708 # I2C + rmmod pl2303 # USB↔Serial cable echo "OK" } diff --git a/raspberrypi/configs/cdfprincipal_defconfig b/raspberrypi/configs/cdfprincipal_defconfig index 964b3dc..af4c8e0 100644 --- a/raspberrypi/configs/cdfprincipal_defconfig +++ b/raspberrypi/configs/cdfprincipal_defconfig @@ -49,16 +49,16 @@ BR2_CCACHE=y BR2_TARGET_GENERIC_HOSTNAME="principal" BR2_TARGET_GENERIC_ISSUE="Robotech - CdF 2018 - Robot principal" -# Configuration noyau supplémentaire -BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="${BR2_EXTERNAL_CDF_PATH}/board/robotech/cdfprincipal/linux-extra.conf" -# TODO Not working - # Paquets nécessaires BR2_PACKAGE_CHEF=y # Fichiers supplémentaires BR2_ROOTFS_OVERLAY="${BR2_EXTERNAL_CDF_PATH}/board/robotech/cdfprincipal/rootfs_overlay/" -BR2_ROOTFS_POST_BUILD_SCRIPT="board/raspberrypi3/post-build.sh ${BR2_EXTERNAL_CDF_PATH}/board/robotech/cdfprincipal/post-build.sh" +BR2_ROOTFS_POST_BUILD_SCRIPT="${BR2_EXTERNAL_CDF_PATH}/board/robotech/cdfprincipal/post-build.sh board/raspberrypi3/post-build.sh" +BR2_ROOTFS_POST_IMAGE_SCRIPT="${BR2_EXTERNAL_CDF_PATH}/board/robotech/cdfprincipal/post-image.sh board/raspberrypi3/post-image.sh" +BR2_PACKAGE_BUSYBOX_CONFIG_FRAGMENT_FILES="${BR2_EXTERNAL_CDF_PATH}/board/robotech/cdfprincipal/busybox-extra.conf" +BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="${BR2_EXTERNAL_CDF_PATH}/board/robotech/cdfprincipal/linux-extra.conf" +# TODO Doesn't work # Ne pas activer la connexion ethernet par défaut BR2_SYSTEM_DHCP="" @@ -72,6 +72,7 @@ BR2_PACKAGE_WPA_SUPPLICANT=y # Pour upgrader à chaud BR2_PACKAGE_DROPBEAR=y BR2_PACKAGE_RSYNC=y +BR2_PACKAGE_PPPD=y # Pour faire plaisir à Geoffrey BR2_PACKAGE_HTOP=y @@ -85,3 +86,7 @@ BR2_PACKAGE_AVRDUDE=y # Pour uploader sur le FPGA BR2_PACKAGE_MERCPCL=y +# Communication I2C +BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y +BR2_PACKAGE_I2C_TOOLS=y +