From 4af0f8c86548ffbcc9bfd1e18edd000a6849bd6b Mon Sep 17 00:00:00 2001 From: Geoffrey Frogeye Date: Tue, 1 May 2018 08:45:02 +0200 Subject: [PATCH] Motor controller via FPGA --- chef/Makefile | 2 +- chef/src/CFsignals.h | 16 +++++ chef/src/buttons.c | 99 +++++++++++++++++++++++++++++++ chef/src/buttons.h | 30 ++++++++++ chef/src/ihm.c | 116 +++++-------------------------------- chef/src/ihm.h | 17 ------ chef/src/movement.c | 97 ++++++++++++++----------------- chef/src/movement.h | 18 ++---- chef/src/parcours.c | 3 +- chef/src/premier.c | 12 ++-- chef/src/testForward.c | 42 ++++++++++++-- fpga/Makefile | 2 +- fpga/Principal.vhd | 67 +++++++++++++++++++-- fpga/Principal_tb.gtkw | 48 ++++++++++++--- fpga/Principal_tb.vhd | 23 +++++++- fpga/communication.vhd | 94 ++++++++++++++++++++---------- fpga/communication_tb.gtkw | 27 +++++++-- fpga/communication_tb.vhd | 64 +++++++++++++++++++- fpga/principal.ucf | 64 +++++++++++++------- fpga/project.cfg | 2 +- fpga/pwm.vhd | 30 ++++++++++ 21 files changed, 602 insertions(+), 271 deletions(-) create mode 100644 chef/src/buttons.c create mode 100644 chef/src/buttons.h create mode 100644 fpga/pwm.vhd diff --git a/chef/Makefile b/chef/Makefile index 2572de1..3a7b35b 100644 --- a/chef/Makefile +++ b/chef/Makefile @@ -11,7 +11,7 @@ CFLAGS_CUSTOM += -g ## Générateurs de drapeaux pour les bibliothèques PKG_CONFIG=pkg-config ## Nom des objets communs -OBJS=CF debug i2c ihm lcd movement parcours points position +OBJS=buttons CF debug i2c ihm lcd movement parcours points position OBJS_O=$(addprefix obj/,$(addsuffix .o,$(OBJS))) # VARIABLES AUTOMATIQUES diff --git a/chef/src/CFsignals.h b/chef/src/CFsignals.h index ee04968..bca450f 100644 --- a/chef/src/CFsignals.h +++ b/chef/src/CFsignals.h @@ -58,5 +58,21 @@ struct __attribute__ ((packed)) F2CT_CAPTs { uint16_t back; }; +// Met à jour la PWM (pour ctrl moteur (EN, IN × 2) × 2) +#define C2FD_PWM 'W' +struct __attribute__ ((packed)) C2FD_PWMs { + uint8_t ena; + uint8_t enb; + uint8_t in; +}; + +// Met à jour la PWM (pour ctrl moteur (EN × 2) × 2) +#define C2FD_PWM2 'w' +struct __attribute__ ((packed)) C2FD_PWM2s { + uint8_t ena; + uint8_t enc; + uint8_t enb; + uint8_t end; +}; #endif diff --git a/chef/src/buttons.c b/chef/src/buttons.c new file mode 100644 index 0000000..a25ea50 --- /dev/null +++ b/chef/src/buttons.c @@ -0,0 +1,99 @@ +#include +#include + +#include "buttons.h" + +// Globales +pthread_t tStdinButton; +enum boutons stdinbutton = none; + +// Fonctions +void configureButtons() +{ + pinMode(BUT_PIN_ROUGE, INPUT); + pullUpDnControl(BUT_PIN_ROUGE, PUD_UP); + pinMode(BUT_PIN_JAUNE, INPUT); + pullUpDnControl(BUT_PIN_JAUNE, PUD_UP); + pinMode(BUT_PIN_TIRETTE, INPUT); + pullUpDnControl(BUT_PIN_TIRETTE, PUD_UP); + + pthread_create(&tStdinButton, NULL, TaskStdinButton, NULL); +} + +bool debunkButton(int pin) +{ + int t; + // Press (cancel if wrong) + for (t = BUT_DEBUNK_TIME / 2; t > 0; t--) { + if (digitalRead(pin) != LOW) { + return false; + } + delay(1); + } + // Release (re-wait if wrong) + for (t = BUT_DEBUNK_TIME / 2; t > 0; t--) { + if (digitalRead(pin) != HIGH) { + t = BUT_DEBUNK_TIME / 2; + } + delay(1); + } + return true; +} + + +void* TaskStdinButton(void* pdata) + +{ + (void)pdata; + + for (;;) { + char c = getchar(); + if (c == '1') { + stdinbutton = jaune; + } else if (c == '2') { + stdinbutton = rouge; + } + } + + return NULL; +} + +enum boutons pressedButton(int timeout) +{ + bool block = timeout < 0; + while (timeout > 0 || block) { + + if (stdinbutton != none) { + enum boutons bout = stdinbutton; + stdinbutton = none; + return bout; + } + + if (debunkButton(BUT_PIN_JAUNE)) { + return jaune; + } + + if (debunkButton(BUT_PIN_ROUGE)) { + return rouge; + } + + delay(BUT_POLLING_INTERVAL); + timeout -= BUT_POLLING_INTERVAL; + } + return none; +} + +bool tirettePresente() +{ + int etat, newEtat; + int t; + for (t = 0; t < BUT_DEBUNK_TIME; t++) { + newEtat = digitalRead(BUT_PIN_TIRETTE); + if (etat != newEtat) { + t = 0; + etat = newEtat; + } + delay(1); + } + return etat == LOW; +} diff --git a/chef/src/buttons.h b/chef/src/buttons.h new file mode 100644 index 0000000..46ab1be --- /dev/null +++ b/chef/src/buttons.h @@ -0,0 +1,30 @@ +#ifndef __BUTTONS_H_ +#define __BUTTONS_H_ + +#include +#include + +// Constants +#define BUT_PIN_ROUGE 0 +#define BUT_PIN_JAUNE 2 +#define BUT_PIN_TIRETTE 3 + +// ms +#define BUT_BLOCK -1 +#define BUT_POLLING_INTERVAL 50 +#define BUT_DEBUNK_TIME 50 +#define BUT_REFRESH_INTERVAL 1000 + +// Structures +enum boutons {none, jaune, rouge}; + +// Public +void configureButtons(); +enum boutons pressedButton(int timeout); // timeout: ms or -1 +bool tirettePresente(); + +// Private +bool debunkButton(int pin); +void* TaskStdinButton(void *pdata); + +#endif diff --git a/chef/src/ihm.c b/chef/src/ihm.c index 8f0636d..9585a30 100644 --- a/chef/src/ihm.c +++ b/chef/src/ihm.c @@ -1,17 +1,16 @@ #include #include -#include #include -#include #include "ihm.h" #include "movement.h" #include "parcours.h" #include "points.h" +#include "lcd.h" +#include "buttons.h" // Globales pthread_t tIHM; -pthread_t tStdinIHM; // Fonctions void configureIHM() @@ -22,15 +21,8 @@ void configureIHM() void startIHM() { - pinMode(IHM_PIN_ROUGE, INPUT); - pullUpDnControl(IHM_PIN_ROUGE, PUD_UP); - pinMode(IHM_PIN_JAUNE, INPUT); - pullUpDnControl(IHM_PIN_JAUNE, PUD_UP); - pinMode(IHM_PIN_TIRETTE, INPUT); - pullUpDnControl(IHM_PIN_TIRETTE, PUD_UP); - + configureButtons(); pthread_create(&tIHM, NULL, TaskIHM, NULL); - pthread_create(&tStdinIHM, NULL, TaskStdinIHM, NULL); pthread_join(tIHM, NULL); } @@ -46,84 +38,6 @@ void diffTimespec(const struct timespec* t1, const struct timespec* t2, struct t } } -bool debunkButtonIHM(int pin) -{ - int t; - // Press (cancel if wrong) - for (t = IHM_DEBUNK_TIME / 2; t > 0; t--) { - if (digitalRead(pin) != LOW) { - return false; - } - delay(1); - } - // Release (re-wait if wrong) - for (t = IHM_DEBUNK_TIME / 2; t > 0; t--) { - if (digitalRead(pin) != HIGH) { - t = IHM_DEBUNK_TIME / 2; - } - delay(1); - } - return true; -} - -enum boutons stdinbutton = none; - -void* TaskStdinIHM(void* pdata) -{ - (void)pdata; - - for (;;) { - char c = getchar(); - if (c == '1') { - stdinbutton = jaune; - } else if (c == '2') { - stdinbutton = rouge; - } - } - - return NULL; -} - -enum boutons pressedIHM(int timeout) -{ - bool block = timeout < 0; - while (timeout > 0 || block) { - - if (stdinbutton != none) { - enum boutons bout = stdinbutton; - stdinbutton = none; - return bout; - } - - if (debunkButtonIHM(IHM_PIN_JAUNE)) { - return jaune; - } - - if (debunkButtonIHM(IHM_PIN_ROUGE)) { - return rouge; - } - - delay(IHM_POLLING_INTERVAL); - timeout -= IHM_POLLING_INTERVAL; - } - return none; -} - -bool tirettePresente() -{ - int etat, newEtat; - int t; - for (t = 0; t < IHM_DEBUNK_TIME; t++) { - newEtat = digitalRead(IHM_PIN_TIRETTE); - if (etat != newEtat) { - t = 0; - etat = newEtat; - } - delay(1); - } - return etat == LOW; -} - bool isDebug = false; bool isOrange = true; bool annuler = false; @@ -152,7 +66,7 @@ void* TaskIHM(void* pdata) if (isDebug) { printToLCD(LCD_LINE_2, "192.168.0.0 TODO"); } - bout = pressedIHM(IHM_REFRESH_INTERVAL); + bout = pressedButton(BUT_REFRESH_INTERVAL); if (bout == rouge) { isDebug = !isDebug; @@ -165,7 +79,7 @@ void* TaskIHM(void* pdata) for (;;) { clearLCD(); printfToLCD(LCD_LINE_1, "Couleur : %s", getCouleur()); - bout = pressedIHM(IHM_BLOCK); + bout = pressedButton(BUT_BLOCK); if (bout == rouge) { isOrange = !isOrange; @@ -184,7 +98,7 @@ void* TaskIHM(void* pdata) printToLCD(LCD_LINE_1, "Calibrer"); printfToLCD(LCD_LINE_2, "(%s)", getCouleur()); } - bout = pressedIHM(IHM_REFRESH_INTERVAL); + bout = pressedButton(BUT_REFRESH_INTERVAL); if (bout == rouge) { clearLCD(); @@ -200,7 +114,7 @@ void* TaskIHM(void* pdata) for (;;) { clearLCD(); printToLCD(LCD_LINE_1, "Diagnostiquer"); - bout = pressedIHM(IHM_BLOCK); + bout = pressedButton(BUT_BLOCK); if (bout == rouge) { clearLCD(); @@ -216,7 +130,7 @@ void* TaskIHM(void* pdata) clearLCD(); printToLCD(LCD_LINE_1, "Lancer parcours"); printfToLCD(LCD_LINE_2, "(%s)", getCouleur()); - bout = pressedIHM(IHM_BLOCK); + bout = pressedButton(BUT_BLOCK); if (bout == rouge) { // No tirette annuler = false; @@ -224,7 +138,7 @@ void* TaskIHM(void* pdata) clearLCD(); printToLCD(LCD_LINE_1, "Inserez tirette"); printToLCD(LCD_LINE_2, "(ROUGE: ignorer)"); - bout = pressedIHM(IHM_REFRESH_INTERVAL); + bout = pressedButton(BUT_REFRESH_INTERVAL); if (bout == rouge) { break; } else if (bout == jaune) { @@ -241,7 +155,7 @@ void* TaskIHM(void* pdata) prepareParcours(isOrange); while (tirettePresente()) { - bout = pressedIHM(IHM_POLLING_INTERVAL); + bout = pressedButton(BUT_POLLING_INTERVAL); if (bout == jaune) { annuler = true; break; @@ -256,15 +170,15 @@ void* TaskIHM(void* pdata) int toWait; while ((toWait = updateParcours()) >= 0) { - if (pressedIHM(toWait) != none) { + if (pressedButton(toWait) != none) { break; } } stopParcours(); - pressedIHM(IHM_BLOCK); // Nécessite 3 appuis pour éviter d'enlever le score par inadvertance - pressedIHM(IHM_BLOCK); - pressedIHM(IHM_BLOCK); + pressedButton(BUT_BLOCK); // Nécessite 3 appuis pour éviter d'enlever le score par inadvertance + pressedButton(BUT_BLOCK); + pressedButton(BUT_BLOCK); } else if (bout == jaune) { break; } @@ -274,7 +188,7 @@ void* TaskIHM(void* pdata) for (;;) { clearLCD(); printToLCD(LCD_LINE_1, "Remettre a zero"); - bout = pressedIHM(IHM_BLOCK); + bout = pressedButton(BUT_BLOCK); if (bout == rouge) { clearLCD(); diff --git a/chef/src/ihm.h b/chef/src/ihm.h index 681cd27..e01fca4 100644 --- a/chef/src/ihm.h +++ b/chef/src/ihm.h @@ -3,20 +3,6 @@ #include -#include "lcd.h" - -#define IHM_PIN_ROUGE 0 -#define IHM_PIN_JAUNE 2 -#define IHM_PIN_TIRETTE 3 - -// ms -#define IHM_BLOCK -1 -#define IHM_POLLING_INTERVAL 50 -#define IHM_DEBUNK_TIME 50 -#define IHM_REFRESH_INTERVAL 1000 - -enum boutons {none, jaune, rouge}; - // Public void configureIHM(); void startIHM(); @@ -24,8 +10,5 @@ void deconfigureIHM(); // Private void* TaskIHM(void *pdata); -void* TaskStdinIHM(void *pdata); -enum boutons pressedIHM(int timeout); // timeout: ms or -1 -bool debunkButtonIHM(int pin); #endif diff --git a/chef/src/movement.c b/chef/src/movement.c index e9402c0..5a07f12 100644 --- a/chef/src/movement.c +++ b/chef/src/movement.c @@ -1,85 +1,74 @@ -#include "movement.h" #include #include #include #include +#include "movement.h" +#include "CF.h" + void configureMovement() { - pinMode(ENA, PWM_OUTPUT); - pinMode(ENB, PWM_OUTPUT); + stop(); } void aller(struct position* pos); int dbg = 0; -int changerMoteurs(float lVit, float rVit) +uint8_t tensionToPWM(float V) { + if (V >= PWM_MAX_V) { + return PWM_MAX; + } else if (V <= 0) { + return 0; + } else { + return V * (float) PWM_MAX / (float) PWM_MAX_V; + } +} + +// Tension de PWM +// TODO Changer en tension de moteur +int setMoteurTension(float lVolt, float rVolt) +{ + static struct C2FD_PWMs msg; + + msg.in = 0x00; + // Gauche - bool lFor = lVit < 0; - float lVolt = fabs(lVit); // TODO Utiliser les vitesses + bool lFor = lVolt < 0; + lVolt = fabs(lVolt); if (lVolt > MOT_MAX_V) { lVolt = MOT_MAX_V; } - if (lVolt < MOT_MIN_V) { - digitalWrite(IN1, LOW); - digitalWrite(IN2, LOW); - printf("x"); - - } else if (lFor) { - digitalWrite(IN1, HIGH); - digitalWrite(IN2, LOW); - printf("↑"); - } else { - digitalWrite(IN1, LOW); - digitalWrite(IN2, HIGH); - printf("↓"); - } - int lAbs = lVolt * PWM_MAX / PWM_MAX_V; - pwmWrite(ENA, lAbs); - printf("%6d", lAbs); + msg.in |= 1 << (lFor ? IN1 : IN2); + msg.ena = tensionToPWM(lVolt); // Droite - bool rFor = rVit < 0; - float rVolt = fabs(rVit); // TODO Utiriser res vitesses - if (rVolt > MOT_MAX_V) { - rVolt = MOT_MAX_V; - } - if (rVolt < MOT_MIN_V) { - digitalWrite(IN3, LOW); - digitalWrite(IN4, LOW); - printf("x"); + bool rFor = rVolt < 0; + rVolt = fabs(rVolt); + msg.in |= 1 << (rFor ? IN3 : IN4); + msg.enb = tensionToPWM(rVolt); - } else if (rFor) { - digitalWrite(IN3, HIGH); - digitalWrite(IN4, LOW); - printf("↑"); - } else { - digitalWrite(IN3, LOW); - digitalWrite(IN4, HIGH); - printf("↓"); - } - int rAbs = rVolt * PWM_MAX / PWM_MAX_V; - pwmWrite(ENB, rAbs); - printf("%6d", rAbs); - printf("\n"); + sendCF(C2FD_PWM, &msg, sizeof(struct C2FD_PWMs)); } +int changerMoteurs(float lVit, float rVit) +{ + // TODO Conversion en vitesse + setMoteurTension(lVit, rVit); +} + +static struct C2FD_PWMs msgBrake = {0, 0, 0x00}; +static struct C2FD_PWMs msgFree = {0, 0, (1 << IN1) | (1 << IN2) | (1 << IN3) | (1 << IN4)}; + int brake() { - digitalWrite(IN1, LOW); - digitalWrite(IN2, LOW); - digitalWrite(IN3, LOW); - digitalWrite(IN4, LOW); + sendCF(C2FD_PWM, &msgBrake, sizeof(struct C2FD_PWMs)); } int freewheel() { - digitalWrite(IN1, HIGH); - digitalWrite(IN2, HIGH); - digitalWrite(IN3, HIGH); - digitalWrite(IN4, HIGH); + sendCF(C2FD_PWM, &msgFree, sizeof(struct C2FD_PWMs)); } void deconfigureMovement() @@ -90,5 +79,5 @@ void deconfigureMovement() int stop() { brake(); - // TODO + // TODO Actionneurs } diff --git a/chef/src/movement.h b/chef/src/movement.h index f5d1f36..5400af2 100644 --- a/chef/src/movement.h +++ b/chef/src/movement.h @@ -7,8 +7,7 @@ #include "position.h" -#include -#define PWM_MAX 1023 +#define PWM_MAX 255 #define PWM_MAX_V 3.3 #define TESTINATOR @@ -24,17 +23,10 @@ #define MOT_MAX_V 2.5 #endif -// Pins definition -// Left -#define ENA 26 -#define IN1 21 -#define IN2 22 - -// Right -#define ENB 23 -#define IN3 24 -#define IN4 25 - +#define IN1 0 +#define IN2 1 +#define IN3 2 +#define IN4 3 void configureMovement(); void aller(struct position* pos); diff --git a/chef/src/parcours.c b/chef/src/parcours.c index cdb3a37..4f79de3 100644 --- a/chef/src/parcours.c +++ b/chef/src/parcours.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "lcd.h" #include "movement.h" @@ -69,7 +70,7 @@ void stopParcours() } #define UP_TIME 1000 -#define HIGH_TIME 30000 +#define HIGH_TIME 3000 #define DOWN_TIME 1000 #define LOW_TIME 2000 #define MAX_VIT MOT_MAX_V diff --git a/chef/src/premier.c b/chef/src/premier.c index 4bd1c52..0c962d8 100644 --- a/chef/src/premier.c +++ b/chef/src/premier.c @@ -24,16 +24,16 @@ int main() srand(time(NULL)); configureDebug(); - /* configureCF(); */ - /* configureMovement(); */ - /* configurePosition(); */ + configureCF(); + configureMovement(); + configurePosition(); startDebug(); startIHM(); - /* deconfigureMovement(); */ - /* deconfigurePosition(); */ - /* deconfigureCF(); */ + deconfigureMovement(); + deconfigurePosition(); + deconfigureCF(); deconfigureIHM(); deconfigureDebug(); return EXIT_SUCCESS; diff --git a/chef/src/testForward.c b/chef/src/testForward.c index 22144a4..ee618bd 100644 --- a/chef/src/testForward.c +++ b/chef/src/testForward.c @@ -4,10 +4,13 @@ #include #include #include +#include #include #include "lcd.h" +#include "CF.h" #include "movement.h" +#include "buttons.h" int main(int argc, char* argv[]) { @@ -15,17 +18,44 @@ int main(int argc, char* argv[]) (void)argc; (void)argv; + wiringPiSetup(); + initI2C(); - initLCD(); - clearLCD(); - printToLCD(LCD_LINE_1, "Forward"); - + configureCF(); + configureButtons(); configureMovement(); for (;;) { - changerMoteurs(1.5, 2); - sleep(1); + clearLCD(); + printToLCD(LCD_LINE_1, "Forward"); + changerMoteurs(3.3, 3.3); + pressedButton(BUT_BLOCK); + + clearLCD(); + printToLCD(LCD_LINE_1, "Right"); + changerMoteurs(-3.3, 3.3); + pressedButton(BUT_BLOCK); + + clearLCD(); + printToLCD(LCD_LINE_1, "Left"); + changerMoteurs(-3.3, -3.3); + pressedButton(BUT_BLOCK); + + clearLCD(); + printToLCD(LCD_LINE_1, "Backward"); + changerMoteurs(3.3, -3.3); + pressedButton(BUT_BLOCK); + + clearLCD(); + printToLCD(LCD_LINE_1, "Brake"); + brake(); + pressedButton(BUT_BLOCK); + + clearLCD(); + printToLCD(LCD_LINE_1, "Free"); + freewheel(); + pressedButton(BUT_BLOCK); } } diff --git a/fpga/Makefile b/fpga/Makefile index a19163d..e76d273 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -163,7 +163,7 @@ isimgui: build/isim_$(TB)$(EXE) # Testing (using ghdl and gtkwave) ########################################################################### -GHDL_FLAGS=--mb-comments +GHDL_FLAGS=--mb-comments --ieee=synopsys %_syntax: %.vhd ghdl -s $(GHDL_FLAGS) "$<" diff --git a/fpga/Principal.vhd b/fpga/Principal.vhd index 55855b8..4d8af25 100644 --- a/fpga/Principal.vhd +++ b/fpga/Principal.vhd @@ -20,7 +20,13 @@ entity Principal is FRONTTRIGGER: out std_logic; FRONTECHO: in std_logic; BACKTRIGGER: out std_logic; - BACKECHO: in std_logic + BACKECHO: in std_logic; + ENA: out std_logic; + IN1ENC: out std_logic; + IN2: out std_logic; + ENB: out std_logic; + IN3END: out std_logic; + IN4: out std_logic ); end Principal; @@ -76,7 +82,22 @@ architecture Behavioral of Principal is ); end component; - -- AF + -- Motor controller + signal enAd : std_logic_vector(7 downto 0); + signal in1enCd : std_logic_vector(7 downto 0); + signal in2d : std_logic; + signal enBd : std_logic_vector(7 downto 0); + signal in3enDd : std_logic_vector(7 downto 0); + signal in4d : std_logic; + component PWM is + port ( + clk : in std_logic; + data : in std_logic_vector (7 downto 0); + pulse : out std_logic + ); + end component; + + -- CF component uart is generic ( baud : positive := fBaud; @@ -116,7 +137,13 @@ architecture Behavioral of Principal is txStb : out std_logic; txAck : in std_logic; rxData : in std_logic_vector(7 downto 0); - rxStb : in std_logic + rxStb : in std_logic; + enA : out std_logic_vector(7 downto 0); + in1enC : out std_logic_vector(7 downto 0); + in2 : out std_logic; + enB : out std_logic_vector(7 downto 0); + in3enD : out std_logic_vector(7 downto 0); + in4 : out std_logic ); end component; @@ -175,9 +202,33 @@ begin signalIn => backRaw, signalOut => back, start => backFinished - -- done => done + -- done => done ); + enAp : PWM port map ( + clk => CLK, + data => enAd, + pulse => ENA + ); + in1enCp : PWM port map ( + clk => CLK, + data => in1enCd, + pulse => IN1ENC + ); + IN2 <= in2d; + + enBp : PWM port map ( + clk => CLK, + data => enBd, + pulse => ENB + ); + + in3enDp : PWM port map ( + clk => CLK, + data => in3enDd, + pulse => IN3END + ); + IN4 <= in4d; FA: uart port map( @@ -204,7 +255,13 @@ begin txStb => txStb, txAck => txAck, rxData => rxData, - rxStb => rxStb + rxStb => rxStb, + enA => enAd, + in1enC => in1enCd, + in2 => in2d, + enB => enBd, + in3enD => in3enDd, + in4 => in4d ); end Behavioral; diff --git a/fpga/Principal_tb.gtkw b/fpga/Principal_tb.gtkw index 6ff2c01..26847f4 100644 --- a/fpga/Principal_tb.gtkw +++ b/fpga/Principal_tb.gtkw @@ -1,20 +1,22 @@ [*] -[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI -[*] Tue Feb 27 18:30:48 2018 +[*] GTKWave Analyzer v3.3.89 (w)1999-2018 BSI +[*] Tue May 1 05:22:50 2018 [*] [dumpfile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/build/Principal_tb.ghw" -[dumpfile_mtime] "Tue Feb 27 18:29:45 2018" -[dumpfile_size] 4891772 +[dumpfile_mtime] "Tue May 1 05:18:35 2018" +[dumpfile_size] 6534540 [savefile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/Principal_tb.gtkw" [timestart] 0 [size] 1600 862 [pos] -1 -1 -*-43.418156 1760000000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +*-43.492355 11010000000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [treeopen] top. [treeopen] top.principal_tb. [treeopen] top.principal_tb.dut. +[treeopen] top.principal_tb.dut.in1encp. +[treeopen] top.principal_tb.dut.in3endp. [sst_width] 213 -[signals_width] 198 +[signals_width] 255 [sst_expanded] 1 [sst_vpaned_height] 296 @28 @@ -95,11 +97,43 @@ top.principal_tb.dut.backcapt.start top.principal_tb.dut.backcapt.trigger [color] 3 top.principal_tb.dut.backcapt.echo -@8421 +@8420 [color] 3 top.principal_tb.dut.backcapt.distancecounter @420 [color] 3 top.principal_tb.dut.back +@22 +[color] 5 +#{top.principal_tb.dut.enad[7:0]} top.principal_tb.dut.enad[7] top.principal_tb.dut.enad[6] top.principal_tb.dut.enad[5] top.principal_tb.dut.enad[4] top.principal_tb.dut.enad[3] top.principal_tb.dut.enad[2] top.principal_tb.dut.enad[1] top.principal_tb.dut.enad[0] +@28 +[color] 5 +top.principal_tb.dut.ena +@22 +[color] 5 +#{top.principal_tb.dut.in1encd[7:0]} top.principal_tb.dut.in1encd[7] top.principal_tb.dut.in1encd[6] top.principal_tb.dut.in1encd[5] top.principal_tb.dut.in1encd[4] top.principal_tb.dut.in1encd[3] top.principal_tb.dut.in1encd[2] top.principal_tb.dut.in1encd[1] top.principal_tb.dut.in1encd[0] +@28 +[color] 5 +top.principal_tb.dut.in1enc +[color] 5 +top.principal_tb.dut.in2d +[color] 5 +top.principal_tb.dut.in2 +@22 +[color] 5 +#{top.principal_tb.dut.enbd[7:0]} top.principal_tb.dut.enbd[7] top.principal_tb.dut.enbd[6] top.principal_tb.dut.enbd[5] top.principal_tb.dut.enbd[4] top.principal_tb.dut.enbd[3] top.principal_tb.dut.enbd[2] top.principal_tb.dut.enbd[1] top.principal_tb.dut.enbd[0] +@28 +[color] 5 +top.principal_tb.dut.enb +@22 +[color] 5 +#{top.principal_tb.dut.in3endd[7:0]} top.principal_tb.dut.in3endd[7] top.principal_tb.dut.in3endd[6] top.principal_tb.dut.in3endd[5] top.principal_tb.dut.in3endd[4] top.principal_tb.dut.in3endd[3] top.principal_tb.dut.in3endd[2] top.principal_tb.dut.in3endd[1] top.principal_tb.dut.in3endd[0] +@28 +[color] 5 +top.principal_tb.dut.in3end +[color] 5 +top.principal_tb.dut.in4d +[color] 5 +top.principal_tb.dut.in4 [pattern_trace] 1 [pattern_trace] 0 diff --git a/fpga/Principal_tb.vhd b/fpga/Principal_tb.vhd index bbe9cad..febb152 100644 --- a/fpga/Principal_tb.vhd +++ b/fpga/Principal_tb.vhd @@ -30,7 +30,13 @@ architecture tb of Principal_tb is FRONTTRIGGER: out std_logic; FRONTECHO: in std_logic; BACKTRIGGER: out std_logic; - BACKECHO: in std_logic + BACKECHO: in std_logic; + ENA: out std_logic; + IN1ENC: out std_logic; + IN2: out std_logic; + ENB: out std_logic; + IN3END: out std_logic; + IN4: out std_logic ); end component; @@ -46,6 +52,12 @@ architecture tb of Principal_tb is signal FRONTECHO : std_logic; signal BACKTRIGGER : std_logic; signal BACKECHO : std_logic; + signal ENA : std_logic; + signal IN1ENC : std_logic; + signal IN2 : std_logic; + signal ENB : std_logic; + signal IN3END : std_logic; + signal IN4 : std_logic; constant TbPeriod : time := 500 ns; signal TbClock : std_logic := '0'; @@ -71,7 +83,14 @@ begin FRONTTRIGGER => FRONTTRIGGER, FRONTECHO => FRONTECHO, BACKTRIGGER => BACKTRIGGER, - BACKECHO => BACKECHO); + BACKECHO => BACKECHO, + ENA => ENA, + IN1ENC => IN1ENC, + IN2 => IN2, + ENB => ENB, + IN3END => IN3END, + IN4 => IN4 + ); -- Clock generation TbClock <= not TbClock after TbPeriod/2 when TbSimEnded /= '1' else '0'; diff --git a/fpga/communication.vhd b/fpga/communication.vhd index b5a40a5..54d333a 100644 --- a/fpga/communication.vhd +++ b/fpga/communication.vhd @@ -16,31 +16,39 @@ entity communication is txStb : out std_logic := '0'; txAck : in std_logic; rxData : in std_logic_vector(7 downto 0); - rxStb : in std_logic + rxStb : in std_logic; + enA : out std_logic_vector(7 downto 0) := x"00"; + in1enC : out std_logic_vector(7 downto 0) := x"00"; + in2 : out std_logic := '0'; + enB : out std_logic_vector(7 downto 0) := x"00"; + in3enD : out std_logic_vector(7 downto 0) := x"00"; + in4 : out std_logic := '0' ); end communication; architecture Behavioral of communication is - constant A2FD_PING : std_logic_vector(7 downto 0) := x"50"; -- 'P' - constant A2FD_RESETCODER : std_logic_vector(7 downto 0) := x"52"; -- 'R' - constant F2AD_ERR : std_logic_vector(7 downto 0) := x"45"; -- 'E' + constant C2FD_PING : std_logic_vector(7 downto 0) := x"50"; -- 'P' + constant C2FD_RESETCODER : std_logic_vector(7 downto 0) := x"52"; -- 'R' + constant F2CD_ERR : std_logic_vector(7 downto 0) := x"45"; -- 'E' constant ERR_UNKNOWN_CODE : std_logic_vector(7 downto 0) := x"43"; -- 'C' - constant F2AI_CODER : std_logic_vector(7 downto 0) := x"44"; -- 'D' - constant F2AI_CAPT : std_logic_vector(7 downto 0) := x"43"; -- 'C' - constant F2AT_CAPT : std_logic_vector(7 downto 0) := x"63"; -- 'c' + constant F2CI_CODER : std_logic_vector(7 downto 0) := x"44"; -- 'D' + constant F2CI_CAPT : std_logic_vector(7 downto 0) := x"43"; -- 'C' + constant F2CT_CAPT : std_logic_vector(7 downto 0) := x"63"; -- 'c' + constant C2FD_PWM : std_logic_vector(7 downto 0) := x"57"; -- 'W' + constant C2FD_PWM2 : std_logic_vector(7 downto 0) := x"77"; -- 'w' signal frontTrigger : integer := 0; signal backTrigger : integer := 0; signal triggerSet : std_logic := '0'; - type readMessages is (F2AT_CAPTs); + type readMessages is (F2CT_CAPTs, C2FD_PWMs, C2FD_PWM2s); signal readMessage : readMessages; signal readSize : integer := 0; signal readOffset : integer := 0; signal readData : std_logic_vector(63 downto 0) := (others => '0'); -- Max message size (will be trimmed down by the synthetizer) - type sendMessages is (A2FD_PINGs, F2AI_CODERs, F2AI_CAPTs, F2AD_ERR_UNKNOWN_CODEs); + type sendMessages is (C2FD_PINGs, F2CI_CODERs, F2CI_CAPTs, F2CD_ERR_UNKNOWN_CODEs); constant SENDQUEUE_SIZE : integer := 16; type sendQueueMemorya is array (0 to SENDQUEUE_SIZE - 1) of sendMessages; signal sendQueueMemory : sendQueueMemorya; @@ -98,17 +106,23 @@ begin if readSize = 0 then -- Beginning of message readSize <= 0; case rxData is - when A2FD_PING => - pushSend(A2FD_PINGs); - when F2AI_CODER => - pushSend(F2AI_CODERs); - when F2AI_CAPT => - pushSend(F2AI_CAPTs); - when F2AT_CAPT => - readMessage <= F2AT_CAPTs; + when C2FD_PING => + pushSend(C2FD_PINGs); + when F2CI_CODER => + pushSend(F2CI_CODERs); + when F2CI_CAPT => + pushSend(F2CI_CAPTs); + when F2CT_CAPT => + readMessage <= F2CT_CAPTs; + readSize <= 4; + when C2FD_PWM => + readMessage <= C2FD_PWMs; + readSize <= 3; + when C2FD_PWM2 => + readMessage <= C2FD_PWM2s; readSize <= 4; when others => - pushSend(F2AD_ERR_UNKNOWN_CODEs); + pushSend(F2CD_ERR_UNKNOWN_CODEs); end case; else -- Rest of message if readOffset < readSize then @@ -118,17 +132,39 @@ begin end if; elsif readSize > 0 and readOffset = readSize then -- Rest of message ended case readMessage is - when F2AT_CAPTs => + when F2CT_CAPTs => frontTrigger <= to_integer(unsigned(readData(15 downto 0))); backTrigger <= to_integer(unsigned(readData(31 downto 16))); triggerSet <= '1'; + when C2FD_PWMs => + enA <= readData(7 downto 0); + enB <= readData(15 downto 8); + if readData(16) = '1' then + in1enC <= x"FF"; + else + in1enC <= x"00"; + end if; + in2 <= readData(17); + if readData(18) = '1' then + in3enD <= x"FF"; + else + in3enD <= x"00"; + end if; + in4 <= readData(19); + when C2FD_PWM2s => + enA <= readData(7 downto 0); + in1enC <= readData(15 downto 8); + enB <= readData(23 downto 16); + in3enD <= readData(31 downto 24); + in2 <= '0'; + in4 <= '0'; when others => - pushSend(F2AD_ERR_UNKNOWN_CODEs); + pushSend(F2CD_ERR_UNKNOWN_CODEs); end case; readOffset <= 0; readSize <= 0; elsif (triggerSet = '1' and ((front > frontTrigger) or (back > backTrigger))) then - pushSend(F2AI_CAPTs); + pushSend(F2CI_CAPTs); triggerSet <= '0'; end if; @@ -146,22 +182,22 @@ begin sendAvailable <= '1'; case sendQueueMemory(sendTail) is - when A2FD_PINGs => - sendData(7 downto 0) <= A2FD_PING; + when C2FD_PINGs => + sendData(7 downto 0) <= C2FD_PING; sendSize <= 1; - when F2AI_CAPTs => - sendData(7 downto 0) <= F2AI_CAPT; + when F2CI_CAPTs => + sendData(7 downto 0) <= F2CI_CAPT; sendData(23 downto 8) <= std_logic_vector(to_signed(front, 16)); sendData(39 downto 24) <= std_logic_vector(to_unsigned(back, 16)); sendSize <= 5; - when F2AI_CODERs => + when F2CI_CODERs => zerocoder <= '1'; - sendData(7 downto 0) <= F2AI_CODER; + sendData(7 downto 0) <= F2CI_CODER; sendData(23 downto 8) <= std_logic_vector(to_signed(left, 16)); sendData(39 downto 24) <= std_logic_vector(to_signed(right, 16)); sendSize <= 5; - when others => -- Including F2AD_ERR_UNKNOWN_CODEs - sendData(7 downto 0) <= F2AD_ERR; + when others => -- Including F2CD_ERR_UNKNOWN_CODEs + sendData(7 downto 0) <= F2CD_ERR; sendData(15 downto 8) <= ERR_UNKNOWN_CODE; sendSize <= 2; end case; diff --git a/fpga/communication_tb.gtkw b/fpga/communication_tb.gtkw index 360e6ee..f8414c8 100644 --- a/fpga/communication_tb.gtkw +++ b/fpga/communication_tb.gtkw @@ -1,15 +1,15 @@ [*] -[*] GTKWave Analyzer v3.3.86 (w)1999-2017 BSI -[*] Wed Feb 28 14:53:10 2018 +[*] GTKWave Analyzer v3.3.89 (w)1999-2018 BSI +[*] Tue May 1 04:06:11 2018 [*] [dumpfile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/build/communication_tb.ghw" -[dumpfile_mtime] "Wed Feb 28 14:51:41 2018" -[dumpfile_size] 7845 +[dumpfile_mtime] "Tue May 1 04:02:41 2018" +[dumpfile_size] 8903 [savefile] "/home/geoffrey/Documents/Polytech/Robotech/2017-2018/CdF/cdf2018-principal/fpga/communication_tb.gtkw" [timestart] 0 [size] 1600 862 [pos] -1 -1 -*-30.009827 1783000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +*-30.189280 1783000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [treeopen] top. [treeopen] top.communication_tb. [treeopen] top.communication_tb.dut. @@ -66,5 +66,22 @@ top.communication_tb.dut.backtrigger top.communication_tb.dut.front [color] 2 top.communication_tb.dut.back +@22 +[color] 6 +#{top.communication_tb.ena[7:0]} top.communication_tb.ena[7] top.communication_tb.ena[6] top.communication_tb.ena[5] top.communication_tb.ena[4] top.communication_tb.ena[3] top.communication_tb.ena[2] top.communication_tb.ena[1] top.communication_tb.ena[0] +[color] 6 +#{top.communication_tb.in1enc[7:0]} top.communication_tb.in1enc[7] top.communication_tb.in1enc[6] top.communication_tb.in1enc[5] top.communication_tb.in1enc[4] top.communication_tb.in1enc[3] top.communication_tb.in1enc[2] top.communication_tb.in1enc[1] top.communication_tb.in1enc[0] +@28 +[color] 6 +top.communication_tb.dut.in2 +@22 +[color] 6 +#{top.communication_tb.enb[7:0]} top.communication_tb.enb[7] top.communication_tb.enb[6] top.communication_tb.enb[5] top.communication_tb.enb[4] top.communication_tb.enb[3] top.communication_tb.enb[2] top.communication_tb.enb[1] top.communication_tb.enb[0] +@80023 +[color] 6 +#{top.communication_tb.in3end[7:0]} top.communication_tb.in3end[7] top.communication_tb.in3end[6] top.communication_tb.in3end[5] top.communication_tb.in3end[4] top.communication_tb.in3end[3] top.communication_tb.in3end[2] top.communication_tb.in3end[1] top.communication_tb.in3end[0] +@28 +[color] 6 +top.communication_tb.dut.in4 [pattern_trace] 1 [pattern_trace] 0 diff --git a/fpga/communication_tb.vhd b/fpga/communication_tb.vhd index 9706350..1e4d818 100644 --- a/fpga/communication_tb.vhd +++ b/fpga/communication_tb.vhd @@ -23,7 +23,14 @@ architecture tb of communication_tb is txStb : out std_logic; txAck : in std_logic; rxData : in std_logic_vector (7 downto 0); - rxStb : in std_logic); + rxStb : in std_logic; + enA : out std_logic_vector(7 downto 0); + in1enC : out std_logic_vector(7 downto 0); + in2 : out std_logic; + enB : out std_logic_vector(7 downto 0); + in3enD : out std_logic_vector(7 downto 0); + in4 : out std_logic + ); end component; signal clock : std_logic; @@ -38,6 +45,12 @@ architecture tb of communication_tb is signal txAck : std_logic; signal rxData : std_logic_vector (7 downto 0); signal rxStb : std_logic; + signal enA : std_logic_vector(7 downto 0); + signal in1enC : std_logic_vector(7 downto 0); + signal in2 : std_logic; + signal enB : std_logic_vector(7 downto 0); + signal in3enD : std_logic_vector(7 downto 0); + signal in4 : std_logic; constant TbPeriod : time := 20 ns; signal TbClock : std_logic := '0'; @@ -59,7 +72,14 @@ begin zerocoder => zerocoder, txAck => txAck, rxData => rxData, - rxStb => rxStb); + rxStb => rxStb, + enA => enA, + in1enC => in1enC, + in2 => in2, + enB => enB, + in3enD => in3enD, + in4 => in4 + ); -- Clock generation TbClock <= not TbClock after TbPeriod/2 when TbSimEnded /= '1' else '0'; @@ -245,6 +265,46 @@ begin wait for 100 ns; + -- Test PWM1 + report "TEST Receiving 'W'" severity note; + + tampon(0 to 3) := (x"57", x"CC", x"77", x"03"); + for I in 0 to 3 loop + rxData <= tampon(I); + rxStb <= '1'; + wait for TbPeriod; + rxStb <= '0'; + wait for TbPeriod; + end loop; + + assert enA = x"CC" report "ENA not at correct value" severity error; + assert enB = x"77" report "ENB not at correct value" severity error; + assert in1enC = x"FF" report "IN1 not at correct value" severity error; + assert in2 = '1' report "IN1 not at correct value" severity error; + assert in3enD = x"00" report "IN3 not at correct value" severity error; + assert in4 = '0' report "IN4 not at correct value" severity error; + + wait for 100 ns; + + -- Test PWM2 + report "TEST Receiving 'w'" severity note; + + tampon(0 to 4) := (x"77", x"11", x"22", x"33", x"44"); + for I in 0 to 4 loop + rxData <= tampon(I); + rxStb <= '1'; + wait for TbPeriod; + rxStb <= '0'; + wait for TbPeriod; + end loop; + + assert enA = x"11" report "ENA not at correct value" severity error; + assert in1enC = x"22" report "ENC not at correct value" severity error; + assert enB = x"33" report "ENB not at correct value" severity error; + assert in3enD = x"44" report "END not at correct value" severity error; + + wait for 100 ns; + TbSimEnded <= '1'; wait; diff --git a/fpga/principal.ucf b/fpga/principal.ucf index 38b8989..2d7556c 100644 --- a/fpga/principal.ucf +++ b/fpga/principal.ucf @@ -7,32 +7,56 @@ TIMESPEC "TS_CLK" = PERIOD "CLK" 20 ns HIGH 50 %; # BTN NET "BTN" LOC = "P41" | IOSTANDARD = LVTTL ; -# IO<0> -NET "RX" LOC = "P59" | IOSTANDARD = LVTTL ; +# IO<10> +NET "RX" LOC = "P85" | IOSTANDARD = LVTTL ; -# IO<1> -NET "TX" LOC = "P60" | IOSTANDARD = LVTTL ; +# IO<11> +NET "TX" LOC = "P84" | IOSTANDARD = LVTTL ; -# IO<2> -NET "LEFTCHA" LOC = "P61" | IOSTANDARD = LVTTL ; +# IO<12> +NET "LEFTCHA" LOC = "P83" | IOSTANDARD = LVTTL ; -# IO<3> -NET "LEFTCHB" LOC = "P62" | IOSTANDARD = LVTTL ; +# IO<13> +NET "LEFTCHB" LOC = "P78" | IOSTANDARD = LVTTL ; -# IO<4> -NET "RIGHTCHA" LOC = "P64" | IOSTANDARD = LVTTL ; +# IO<14> +NET "RIGHTCHA" LOC = "P77" | IOSTANDARD = LVTTL ; -# IO<5> -NET "RIGHTCHB" LOC = "P57" | IOSTANDARD = LVTTL ; +# IO<15> +NET "RIGHTCHB" LOC = "P65" | IOSTANDARD = LVTTL ; -# IO<6> -NET "FRONTTRIGGER" LOC = "P56" | IOSTANDARD = LVTTL ; +# IO<16> +NET "FRONTTRIGGER" LOC = "P70" | IOSTANDARD = LVTTL ; -# IO<7> -NET "FRONTECHO" LOC = "P52" | IOSTANDARD = LVTTL ; +# IO<17> +NET "FRONTECHO" LOC = "P71" | IOSTANDARD = LVTTL ; -# IO<8> -NET "BACKTRIGGER" LOC = "P50" | IOSTANDARD = LVTTL ; +# IO<18> +NET "BACKTRIGGER" LOC = "P72" | IOSTANDARD = LVTTL ; -# IO<9> -NET "BACKECHO" LOC = "P49" | IOSTANDARD = LVTTL ; +# IO<19> +NET "BACKECHO" LOC = "P73" | IOSTANDARD = LVTTL ; + +# IO<20> +NET "ENA" LOC = "P5" | IOSTANDARD = LVTTL ; + + +# IO<21> +NET "IN1ENC" LOC = "P4" | IOSTANDARD = LVTTL ; + +# IO<22> +NET "IN2" LOC = "P6" | IOSTANDARD = LVTTL ; + +# IO<23> +NET "ENB" LOC = "P98" | IOSTANDARD = LVTTL ; + +# IO<24> +NET "IN3END" LOC = "P94" | IOSTANDARD = LVTTL ; + +# IO<25> +NET "IN4" LOC = "P93" | IOSTANDARD = LVTTL ; + +# NET "IO<26>" LOC = "P90" | IOSTANDARD = LVTTL ; +# NET "IO<27>" LOC = "P89" | IOSTANDARD = LVTTL ; +# NET "IO<28>" LOC = "P88" | IOSTANDARD = LVTTL ; +# NET "IO<29>" LOC = "P86" | IOSTANDARD = LVTTL ; diff --git a/fpga/project.cfg b/fpga/project.cfg index 41c1623..f233cf4 100644 --- a/fpga/project.cfg +++ b/fpga/project.cfg @@ -5,5 +5,5 @@ PROGRAMMER = mercpcl TOPLEVEL = Principal # Prod -VHDSOURCE = $(TOPLEVEL).vhd communication.vhd uart.vhd hedm.vhd hcsr04.vhd fir.vhd +VHDSOURCE = $(TOPLEVEL).vhd communication.vhd uart.vhd hedm.vhd hcsr04.vhd fir.vhd pwm.vhd CONSTRAINTS = principal.ucf diff --git a/fpga/pwm.vhd b/fpga/pwm.vhd new file mode 100644 index 0000000..64391be --- /dev/null +++ b/fpga/pwm.vhd @@ -0,0 +1,30 @@ +-- Inspiré de http://www.fpga4fun.com/PWM_DAC_2.html + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.NUMERIC_STD.ALL; + +entity PWM is + port ( + clk : in std_logic; + data : in std_logic_vector (7 downto 0) := "00000000"; + pulse : out std_logic + ); +end PWM; + +architecture Behavioral of PWM is + signal accuI : integer; + signal dataI : integer; +begin + + dataI <= to_integer(unsigned(data)); + + process(clk, data) + begin + if rising_edge(clk) then + accuI <= accuI mod 256 + dataI + 1; + end if; + end process; + + pulse <= '1' when accuI >= 256 else '0'; +end Behavioral;