mirror of
https://github.com/RobotechLille/cdf2018-principal
synced 2025-09-04 01:05:56 +02:00
Arduino↔Chef: Ajout côté chef & corrections
This commit is contained in:
parent
0a9009d0c3
commit
45151e7b1a
25 changed files with 669 additions and 166 deletions
|
@ -5,7 +5,7 @@ CC=gcc
|
|||
# Bibliothèques
|
||||
LIBS=
|
||||
## Drapeaux pour le linker
|
||||
LDFLAGS=
|
||||
LDFLAGS=-lpthread
|
||||
## Drapeaux pour le compilateur
|
||||
CFLAGS=
|
||||
## Générateurs de drapeaux pour les bibliothèques
|
||||
|
@ -37,7 +37,7 @@ endif
|
|||
default: bin/testpin bin/premier
|
||||
|
||||
# Binaires (dont il faut spécifier les objets explicitement)
|
||||
bin/premier: obj/common.o obj/serial.o
|
||||
bin/premier: obj/CA.o obj/debug.o obj/movement.o
|
||||
bin/testPin: obj/testPin.o
|
||||
$(CC) $(LDFLAGS) $^ -lwiringPi -o $@
|
||||
|
||||
|
|
178
chef/src/CA.c
Normal file
178
chef/src/CA.c
Normal file
|
@ -0,0 +1,178 @@
|
|||
#include "CA.h"
|
||||
#include <fcntl.h> // O_*
|
||||
#include <stdio.h> // printf...
|
||||
#include <stdlib.h> // stuff
|
||||
#include <string.h> // memcpy
|
||||
#include <strings.h> // bzero
|
||||
#include <unistd.h> // read(), write()...
|
||||
|
||||
void printData(void* data, size_t size)
|
||||
{
|
||||
printf(" ");
|
||||
unsigned char* p = data;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
if (*p >= ' ' && *p <= '~') {
|
||||
printf(" %c", *p);
|
||||
} else {
|
||||
printf(" %02x", *p);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void configureArduino()
|
||||
{
|
||||
// Connection au port série
|
||||
printf("Connexion à %s... ", ARDUINO_PORTNAME);
|
||||
arduino = open(ARDUINO_PORTNAME, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (arduino < 0) {
|
||||
printf("Échec !\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Configuration du port série
|
||||
struct termios cfg;
|
||||
bzero(&cfg, sizeof(cfg));
|
||||
cfg.c_cflag = CLOCAL | CREAD | CA_BAUDRATE | CS8;
|
||||
cfg.c_iflag = 0;
|
||||
cfg.c_oflag = 0;
|
||||
cfg.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */
|
||||
cfg.c_cc[VTIME] = 0; /* inter-character timer unused */
|
||||
cfg.c_cc[VMIN] = 1; /* blocking read until 1 char received */
|
||||
if (tcsetattr(arduino, TCSANOW, &cfg) < 0) {
|
||||
perror("serialConfig.tcsetattr");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
// Flush
|
||||
unsigned char trash[1024];
|
||||
read(arduino, &trash, sizeof(trash));
|
||||
|
||||
printf("OK!\n");
|
||||
}
|
||||
|
||||
void deconfigureArduino()
|
||||
{
|
||||
close(arduino);
|
||||
printf("Déconnecté\n");
|
||||
}
|
||||
|
||||
void registerRxHandler(unsigned char code, rxHandler handler)
|
||||
{
|
||||
rxHandlersAC[code] = handler;
|
||||
}
|
||||
|
||||
void* TaskReaderAC(void* pdata)
|
||||
{
|
||||
(void)pdata;
|
||||
unsigned char code;
|
||||
for (;;) {
|
||||
code = readByteCA();
|
||||
|
||||
#ifdef PRINTRAWDATA
|
||||
printf("↓");
|
||||
printData(&code, sizeof(code));
|
||||
#endif
|
||||
rxHandler handler = rxHandlersAC[code];
|
||||
if (handler != NULL) {
|
||||
handler();
|
||||
} else {
|
||||
printf("Code inconnu: %x (%c)\n", code, code);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void onA2CD_ERR()
|
||||
{
|
||||
struct A2CD_ERRs s;
|
||||
readCA(&s, sizeof(struct A2CD_ERRs));
|
||||
printf("Erreur reçue : %c (%2x)\n", s.code, s.code);
|
||||
}
|
||||
|
||||
void configureCA()
|
||||
{
|
||||
configureArduino();
|
||||
for (int i = 0; i < 256; i++) {
|
||||
rxHandlersAC[i] = NULL;
|
||||
}
|
||||
|
||||
pthread_mutex_init(&sSendCA, NULL);
|
||||
pthread_create(&tReaderAC, NULL, TaskReaderAC, NULL);
|
||||
registerRxHandler(A2CD_ERR, onA2CD_ERR);
|
||||
}
|
||||
|
||||
void deconfigureCA()
|
||||
{
|
||||
deconfigureArduino();
|
||||
}
|
||||
|
||||
void sendByteCA(unsigned char data)
|
||||
{
|
||||
write(arduino, &data, sizeof(data));
|
||||
|
||||
#ifdef PRINTRAWDATA
|
||||
printf("↑");
|
||||
printData(&data, sizeof(data));
|
||||
#endif
|
||||
}
|
||||
|
||||
void sendCA(unsigned char code, void* data, size_t size)
|
||||
{
|
||||
pthread_mutex_lock(&sSendCA);
|
||||
|
||||
sendByteCA(code);
|
||||
if (size > 0) {
|
||||
unsigned char* p = data;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
write(arduino, p, sizeof(unsigned char));
|
||||
p++;
|
||||
}
|
||||
// Envoyer plus d'un octet d'un coup curieusement il aime pas ça du tout
|
||||
}
|
||||
pthread_mutex_unlock(&sSendCA);
|
||||
|
||||
#ifdef PRINTRAWDATA
|
||||
if (size > 0) {
|
||||
printf("↑");
|
||||
printData(data, size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned char readByteCA()
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
while (read(arduino, &c, sizeof(c)) < 1) {
|
||||
sleep(0);
|
||||
}
|
||||
return c;
|
||||
|
||||
#ifdef PRINTRAWDATA
|
||||
printf("↓");
|
||||
printData(&c, sizeof(c));
|
||||
#endif
|
||||
}
|
||||
|
||||
void readCA(void* data, size_t size)
|
||||
{
|
||||
size_t remaining = size;
|
||||
int justRead;
|
||||
char* p = data;
|
||||
do {
|
||||
justRead = read(arduino, p, remaining);
|
||||
if (justRead > 0) {
|
||||
p += justRead;
|
||||
remaining -= justRead;
|
||||
}
|
||||
} while (remaining > 0);
|
||||
|
||||
#ifdef PRINTRAWDATA
|
||||
printf("↓");
|
||||
printData(data, size);
|
||||
#endif
|
||||
}
|
29
chef/src/CA.h
Normal file
29
chef/src/CA.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef __AC_H_
|
||||
#define __AC_H_
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <pthread.h>
|
||||
#include <termios.h> // baudrates
|
||||
|
||||
#include "ACsignals.h"
|
||||
|
||||
#define ARDUINO_PORTNAME "/dev/ttyACM0"
|
||||
#define CA_BAUDRATE B9600
|
||||
// #define PRINTRAWDATA
|
||||
|
||||
int arduino;
|
||||
pthread_mutex_t sSendCA;
|
||||
pthread_t tReaderAC;
|
||||
|
||||
typedef void (*rxHandler)(void);
|
||||
rxHandler rxHandlersAC[256];
|
||||
|
||||
void registerRxHandler(unsigned char code, rxHandler handler); // À utiliser après configureCA();
|
||||
void sendByteCA(unsigned char data); // Privé
|
||||
void sendCA(unsigned char code, void* data, size_t size);
|
||||
unsigned char readByteCA(); // À utiliser uniquement depuis un rxHandler
|
||||
void readCA(void* data, size_t size); // À utiliser uniquement depuis un rxHandler
|
||||
void configureCA();
|
||||
void deconfigureCA();
|
||||
|
||||
#endif
|
|
@ -1 +0,0 @@
|
|||
#include "common.h"
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef __COMMON_H_
|
||||
#define __COMMON_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define SIGNAL_AVANCER 42
|
||||
|
||||
#endif
|
||||
|
52
chef/src/debug.c
Normal file
52
chef/src/debug.c
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include "debug.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h> // sleep
|
||||
|
||||
void* TaskDebug(void* pdata)
|
||||
{
|
||||
(void)pdata;
|
||||
struct timespec tim;
|
||||
/* tim.tv_sec = 0; */
|
||||
/* tim.tv_nsec = 100000000L; */
|
||||
tim.tv_sec = 1;
|
||||
tim.tv_nsec = 0;
|
||||
|
||||
for (;;) {
|
||||
nanosleep(&tim, NULL);
|
||||
sendCA(A2CI_DBG, NULL, 0);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void printDebugInfos(struct A2CI_DBGs* debug)
|
||||
{
|
||||
printf("← Position actuelle (%f; %f) (%f°)", debug->actuel.x, debug->actuel.y, debug->actuel.o);
|
||||
printf(", destination : ");
|
||||
if (debug->movement == C2AD_STOP) {
|
||||
printf("aucune\n");
|
||||
} else {
|
||||
printf("(%f; %f) (%f°)\n", debug->destination.x, debug->destination.y, debug->destination.o);
|
||||
}
|
||||
}
|
||||
|
||||
void onA2CI_DBG()
|
||||
{
|
||||
readCA(&debug, sizeof(struct A2CI_DBGs));
|
||||
printDebugInfos(&debug);
|
||||
}
|
||||
|
||||
void configureDebug()
|
||||
{
|
||||
registerRxHandler(A2CI_DBG, onA2CI_DBG);
|
||||
#ifdef REGULARREPORTS
|
||||
pthread_create(&tDebug, NULL, TaskDebug, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void deconfigureDebug()
|
||||
{
|
||||
#ifdef REGULARREPORTS
|
||||
pthread_cancel(tDebug);
|
||||
#endif
|
||||
}
|
16
chef/src/debug.h
Normal file
16
chef/src/debug.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef __DEBUG_H_
|
||||
#define __DEBUG_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include "CA.h"
|
||||
#define REGULARREPORTS
|
||||
|
||||
struct A2CI_DBGs debug;
|
||||
pthread_t tDebug;
|
||||
|
||||
void* TaskDebug(void *pdata);
|
||||
void onA2CI_DBG();
|
||||
void configureDebug();
|
||||
void deconfigureDebug();
|
||||
|
||||
#endif
|
55
chef/src/movement.c
Normal file
55
chef/src/movement.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include "movement.h"
|
||||
#include "CA.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void onC2AD_STOP()
|
||||
{
|
||||
// On considère que l'arrêt se fait très rapidement pour ne pas
|
||||
// avoir à attendre le signal de retour de C2AD_STOP
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
printf("→ Arrêt\n");
|
||||
sendCA(C2AD_STOP, NULL, 0);
|
||||
registerRxHandler(C2AD_STOP, onC2AD_STOP);
|
||||
}
|
||||
|
||||
// Inspiré de https://stackoverflow.com/a/1760819
|
||||
pthread_mutex_t reponseMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_cond_t reponseCond = PTHREAD_COND_INITIALIZER;
|
||||
bool attenteReponse = false;
|
||||
|
||||
void onC2AD_GOTO()
|
||||
{
|
||||
pthread_mutex_lock(&reponseMutex);
|
||||
attenteReponse = false;
|
||||
pthread_cond_signal(&reponseCond);
|
||||
pthread_mutex_unlock(&reponseMutex);
|
||||
}
|
||||
|
||||
void aller(struct position* pos)
|
||||
{
|
||||
printf("→ Déplacement vers (%f; %f) (%f°)\n", pos->x, pos->y, pos->o);
|
||||
|
||||
if (attenteReponse) {
|
||||
printf("Déjà en déplacement !\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
attenteReponse = true;
|
||||
|
||||
registerRxHandler(C2AD_GOTO, onC2AD_GOTO);
|
||||
sendCA(C2AD_GOTO, (struct C2AD_GOTOs*)pos, sizeof(struct C2AD_GOTOs));
|
||||
|
||||
pthread_mutex_lock(&reponseMutex);
|
||||
while (attenteReponse) {
|
||||
pthread_cond_wait(&reponseCond, &reponseMutex);
|
||||
}
|
||||
pthread_mutex_unlock(&reponseMutex);
|
||||
|
||||
registerRxHandler(C2AD_GOTO, NULL);
|
||||
|
||||
printf("← Arrivé à destination\n");
|
||||
}
|
9
chef/src/movement.h
Normal file
9
chef/src/movement.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __MOVEMENT_H_
|
||||
#define __MOVEMENT_H_
|
||||
|
||||
#include "CA.h"
|
||||
|
||||
void stop();
|
||||
void aller(struct position* pos);
|
||||
|
||||
#endif
|
|
@ -1,15 +1,59 @@
|
|||
#include "premier.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h> // random seed
|
||||
#include <pthread.h>
|
||||
#include <unistd.h> // sleep
|
||||
|
||||
#include "serial.h"
|
||||
#include "CA.h"
|
||||
#include "movement.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define TEMPSMAX 10
|
||||
|
||||
void* TaskParcours(void *pdata)
|
||||
{
|
||||
(void) pdata;
|
||||
|
||||
struct position pos;
|
||||
for (;;) {
|
||||
pos.x = (int) (rand()*200.0/RAND_MAX);
|
||||
pos.y = (int) (rand()*100.0/RAND_MAX);
|
||||
pos.o = (int) (rand()*360.0/RAND_MAX);
|
||||
aller(&pos);
|
||||
sleep(1);
|
||||
stop();
|
||||
sleep(2);
|
||||
}
|
||||
|
||||
printf("Fin du parcours\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
unsigned char g;
|
||||
|
||||
printf("Démarrage...\n");
|
||||
configureCA();
|
||||
sendByteCA('c');
|
||||
while ((g = readByteCA())) {
|
||||
printf("%c\n", g);
|
||||
}
|
||||
configureDebug();
|
||||
srand(time(NULL));
|
||||
|
||||
/* printf("Synchronisation avec le Raspberry Pi\n"); // TODO */
|
||||
|
||||
/* printf("En attente de la tirette...\n"); // TODO */
|
||||
printf("C'est parti !\n");
|
||||
|
||||
pthread_t tParcours;
|
||||
pthread_create(&tParcours, NULL, TaskParcours, NULL);
|
||||
|
||||
sleep(TEMPSMAX);
|
||||
|
||||
printf("Fin des %d secondes\n", TEMPSMAX);
|
||||
/* pthread_cancel(tParcours); */
|
||||
|
||||
|
||||
/* stop(); */
|
||||
/* */
|
||||
deconfigureDebug();
|
||||
deconfigureCA();
|
||||
return 0;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
#ifndef __PREMIER_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#endif
|
|
@ -1,58 +0,0 @@
|
|||
#include "serial.h"
|
||||
#include <stdio.h> // printf...
|
||||
#include <stdlib.h> // stuff
|
||||
#include <unistd.h> // read(), write()...
|
||||
#include <fcntl.h> // O_*
|
||||
#include <strings.h> // bzero
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void configureCA()
|
||||
{
|
||||
// Connection au port série
|
||||
printf("Connexion à %s... ", ARDUINO_PORTNAME);
|
||||
arduino = open(ARDUINO_PORTNAME, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (arduino < 0) {
|
||||
printf("Échec !\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Configuration du port série
|
||||
struct termios cfg;
|
||||
bzero(&cfg, sizeof(cfg));
|
||||
cfg.c_cflag = CLOCAL | CREAD | CA_BAUDRATE | CS8;
|
||||
cfg.c_iflag = 0;
|
||||
cfg.c_oflag = 0;
|
||||
cfg.c_lflag = 0; /* set input mode (non-canonical, no echo,...) */
|
||||
cfg.c_cc[VTIME] = 0; /* inter-character timer unused */
|
||||
cfg.c_cc[VMIN] = 1; /* blocking read until 1 char received */
|
||||
if (tcsetattr(arduino, TCSANOW, &cfg) < 0) {
|
||||
perror("serialConfig.tcsetattr");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
printf("OK!\n");
|
||||
}
|
||||
|
||||
void deconfigureCA() {
|
||||
close(arduino);
|
||||
}
|
||||
|
||||
void sendByteCA(unsigned char data) {
|
||||
write(arduino, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void sendCA(unsigned char code, void* data, size_t size)
|
||||
{
|
||||
sendByteCA(code);
|
||||
write(arduino, data, size);
|
||||
}
|
||||
|
||||
unsigned char readByteCA() {
|
||||
unsigned char c;
|
||||
while (read(arduino, &c, sizeof(c)) < 1) {
|
||||
}
|
||||
return c;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef __SERIAL_H_
|
||||
#define __SERIAL_H_
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h> // baudrates
|
||||
|
||||
#include "ACsignals.h"
|
||||
|
||||
#define ARDUINO_PORTNAME "/dev/ttyACM0"
|
||||
#define CA_BAUDRATE B9600
|
||||
|
||||
int arduino;
|
||||
|
||||
void configureCA();
|
||||
void deconfigureCA();
|
||||
void sendByteCA(unsigned char data);
|
||||
unsigned char readByteCA();
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue