add drive management

This commit is contained in:
Rémi Heredero 2023-08-31 20:02:41 +02:00
parent 2ece901b08
commit a20667399b
8 changed files with 459 additions and 40 deletions

View File

@ -171,8 +171,9 @@ void CM_processIncome(uint8_t idSender, uint8_t idMsg, uint32_t data){
KART_CST.JOYSTICK_PARAM2 = MEM_read_1_byte(MEMADD_JOYSTICK_PARAM2); KART_CST.JOYSTICK_PARAM2 = MEM_read_1_byte(MEMADD_JOYSTICK_PARAM2);
KART_CST.JOYSTICK_ALIVE_TIME = MEM_read_1_byte(MEMADD_JOYSTICK_ALIVE_TIME); KART_CST.JOYSTICK_ALIVE_TIME = MEM_read_1_byte(MEMADD_JOYSTICK_ALIVE_TIME);
ALIVE_setAliveTime(ALjoy(), KART_CST.JOYSTICK_ALIVE_TIME); ALIVE_setAliveTime(ALjoy(), KART_CST.JOYSTICK_ALIVE_TIME);
ALIVE_emitBorn(ALjoy(), 0, 0); ALIVE_emitResurrect(ALjoy(), 0, 0);
ALIVE_emitReady(ALjoy(), 100, 0); ALIVE_emitBorn(ALjoy(), 100, 0);
ALIVE_emitReady(ALjoy(), 200, 0);
} }
} }
break; break;
@ -204,18 +205,18 @@ void CM_processIncome(uint8_t idSender, uint8_t idMsg, uint32_t data){
rpm.separate.byte2 = tmpData.separate.byte1; rpm.separate.byte2 = tmpData.separate.byte1;
rpm.separate.byte3 = tmpData.separate.byte0; rpm.separate.byte3 = tmpData.separate.byte0;
calcSpeed(rpm.full); calcSpeed(rpm.full);
DRIVE_emitPollSpeed(drive());
} }
if(idMsg == 0xF) { // DRIVE_ALIVE if(idMsg == 0xF) { // DRIVE_ALIVE
// statusH statusL - - // statusH statusL - -
ALIVE_ISALIVE(ALdrive()); ALIVE_ISALIVE(&drive()->myChecker);
if(ALdrive()->state == STAL_DEAD){ if(drive()->myChecker.state == STAL_DEAD){
KART_CST.DRIVE_SPEED_TIME = MEM_read_1_byte(MEMADD_DRIVE_SPEED_TIME); KART_CST.DRIVE_SPEED_TIME = MEM_read_1_byte(MEMADD_DRIVE_SPEED_TIME);
KART_CST.DRIVE_STOP_TIME = MEM_read_1_byte(MEMADD_DRIVE_STOP_TIME); KART_CST.DRIVE_STOP_TIME = MEM_read_1_byte(MEMADD_DRIVE_STOP_TIME);
KART_CST.DRIVE_ALIVE_TIME = MEM_read_1_byte(MEMADD_DRIVE_ALIVE_TIME); KART_CST.DRIVE_ALIVE_TIME = MEM_read_1_byte(MEMADD_DRIVE_ALIVE_TIME);
ALIVE_setAliveTime(ALdrive(), KART_CST.DRIVE_ALIVE_TIME); ALIVE_emitResurrect(&drive()->myChecker, 0, 0);
ALIVE_emitBorn(ALdrive(), 0, 0); ALIVE_emitBorn(&drive()->myChecker, 0, 0);
ALIVE_emitReady(ALdrive(), 100, 0);
} }
// TODO drive say ALIVE // TODO drive say ALIVE

View File

@ -0,0 +1,171 @@
/**
* @author Rémi Heredero
* @version 1.0.0
* @date August 2023
* @file drive.c
*/
#include "drive.h"
#include "car.h"
#include "can_message.h"
void DRIVE_init(DRIVE* me){
me->state = STDR_INIT;
ALIVE_init(&me->myChecker);
ALIVE_onSetup(&me->myChecker, CM_DRIVE_SETUP, NULL);
ALIVE_onWait(&me->myChecker, DRIVE_emitStart, me);
ALIVE_onDead(&me->myChecker, DRIVE_emitStop, me);
ALIVE_onBorn(&me->myChecker, DRIVE_emitResurrect, me);
me->wait.f = NULL;
me->run.f = NULL;
me->dead.f = NULL;
}
void DRIVE_startBehaviour(DRIVE* me){
POST(me, &DRIVE_processEvent, evDRinit, 0, 0);
}
bool DRIVE_processEvent(Event* ev) {
bool processed = false;
DRIVE* me = (DRIVE*)Event_getTarget(ev);
DRIVE_STATES oldState = me->state;
evIDT evid = Event_getId(ev);
uint64_t data = Event_getData(ev);
switch (me->state) { // onState
case STDR_INIT:
if (ev->id == evDRinit) {
me->state = STDR_WAIT;
ALIVE_startBehaviourChecker(&me->myChecker); // Start alive checker
}
break;
case STDR_WAIT:
if (ev->id == evDRstart) {
me->state = STDR_RUN;
}
ALIVE_setAliveTime(&me->myChecker, KART_CST.DRIVE_ALIVE_TIME);
ALIVE_emitBorn(&me->myChecker, 100, 0); // Born after 100 ms
ALIVE_emitReady(&me->myChecker, 200, 0); // Ready after 200 ms
break;
case STDR_RUN:
if (ev->id == evDRstop) {
me->state = STDR_DEAD;
}
if (ev->id == evDRpollTorque) {
CM_DRIVE_POWER(&eKart.torque);
}
if (ev->id == evDRpollSpeed) {
CM_DISPLAY_SPEED(&eKart.speed);
}
DRIVE_emitPollTorque(me, KART_CST.DRIVE_STOP_TIME*9, 0);
break;
case STDR_DEAD:
if (ev->id == evDRresurrect) {
me->state = STDR_WAIT;
}
break;
}
if(oldState != me->state){
switch (oldState) { // onExit
case STDR_INIT:
break;
case STDR_WAIT:
break;
case STDR_RUN:
break;
case STDR_DEAD:
break;
}
switch (me->state) { // onEntry
case STDR_INIT:
break;
case STDR_WAIT:
if (me->wait.f != NULL) {
me->wait.f(me->wait.p);
}
break;
case STDR_RUN:
if (me->run.f != NULL) {
me->run.f(me->run.p);
}
break;
case STDR_DEAD:
if (me->dead.f != NULL) {
me->dead.f(me->dead.p);
}
break;
}
processed = true;
}
return processed;
}
/*************
* Callbacks *
*************/
void DRIVE_onWait(DRIVE* me, DRIVE_CALLBACK_FUNCTION f, void* p) {
me->wait.f = f;
me->wait.p = p;
}
void DRIVE_onRun(DRIVE* me, DRIVE_CALLBACK_FUNCTION f, void* p) {
me->run.f = f;
me->run.p = p;
}
void DRIVE_onDead(DRIVE* me, DRIVE_CALLBACK_FUNCTION f, void* p) {
me->dead.f = f;
me->dead.p = p;
}
/************
* EMITTERS *
************/
void DRIVE_emitStart(void* p) {
DRIVE* me = (DRIVE*) p;
POST(me, &DRIVE_processEvent, evDRstart, 0, 0);
}
void DRIVE_emitStop(void* p) {
DRIVE* me = (DRIVE*) p;
POST(me, &DRIVE_processEvent, evDRstop, 0, 0);
}
void DRIVE_emitResurrect(void* p) {
DRIVE* me = (DRIVE*) p;
POST(me, &DRIVE_processEvent, evDRresurrect, 0, 0);
}
void DRIVE_emitPollSpeed(void* p) {
DRIVE* me = (DRIVE*) p;
POST(me, &DRIVE_processEvent, evDRpollSpeed, 0, 0);
}
void DRIVE_emitPollTorque(DRIVE* me, uint16_t t, int64_t data) {
POST(me, &DRIVE_processEvent, evDRpollTorque, t, data);
}
/***********
* SETTERS *
***********/
void DRIVE_setMyChecker(DRIVE* me, ALIVE v) {
me->myChecker = v;
}

View File

@ -0,0 +1,130 @@
/**
* @author Rémi Heredero
* @version 1.0.0
* @date August 2023
* @file drive.h
*/
#ifndef DRIVE_H
#define DRIVE_H
#include "../xf/xf.h"
#include "../middleware/alive.h"
typedef enum {
STDR_INIT,
STDR_WAIT,
STDR_RUN,
STDR_DEAD
} DRIVE_STATES;
typedef enum {
evDRinit = 100,
evDRstart,
evDRstop,
evDRresurrect,
evDRpollSpeed,
evDRpollTorque
} DRIVE_EVENTS;
typedef void (*DRIVE_CALLBACK_FUNCTION)(void*);
typedef struct {
DRIVE_CALLBACK_FUNCTION f; // function
void* p; // param(s)
} DRIVE_CALLBACK;
typedef struct {
DRIVE_STATES state;
ALIVE myChecker;
DRIVE_CALLBACK wait;
DRIVE_CALLBACK run;
DRIVE_CALLBACK dead;
} DRIVE;
/**
* Initialize the DRIVE
* @param me the DRIVE itself
*/
void DRIVE_init(DRIVE* me);
/**
* Start the DRIVE state machine
* @param me the DRIVE itself
*/
void DRIVE_startBehaviour(DRIVE* me);
/**
* Process the event
* @param ev the event to process
* @return true if the event is processed
*/
bool DRIVE_processEvent(Event* ev);
/*************
* Callbacks *
*************/
/**
* Set the callback function to call when the DRIVE is entering state wait
* @param me the DRIVE itself
* @param f the function to call
* @param p the param(s) to pass to the function
*/
void DRIVE_onWait(DRIVE* me, DRIVE_CALLBACK_FUNCTION f, void* p);
/**
* Set the callback function to call when the DRIVE is entering state run
* @param me the DRIVE itself
* @param f the function to call
* @param p the param(s) to pass to the function
*/
void DRIVE_onRun(DRIVE* me, DRIVE_CALLBACK_FUNCTION f, void* p);
/**
* Set the callback function to call when the DRIVE is entering state dead
* @param me the DRIVE itself
* @param f the function to call
* @param p the param(s) to pass to the function
*/
void DRIVE_onDead(DRIVE* me, DRIVE_CALLBACK_FUNCTION f, void* p);
/************
* EMITTERS *
************/
/**
* Emit the start event
* @param p the DRIVE itself
*/
void DRIVE_emitStart(void* p);
/**
* Emit the stop event
* @param p the DRIVE itself
*/
void DRIVE_emitStop(void* p);
/**
* Emit the resurrect event
* @param p the DRIVE itself
*/
void DRIVE_emitResurrect(void* p);
/**
* Emit the pollSpeed event
* @param p the DRIVE itself
*/
void DRIVE_emitPollSpeed(void* p);
/**
* Emit the pollTorque event
* @param p the DRIVE itself
*/
void DRIVE_emitPollTorque(DRIVE* me, uint16_t t, int64_t data);
/***********
* SETTERS *
***********/
#endif

View File

@ -42,8 +42,8 @@ ALIVE* ALjoy(){
return &theFactory.ALjoy_; return &theFactory.ALjoy_;
} }
ALIVE* ALdrive(){ DRIVE* drive(){
return &theFactory.ALdrive_; return &theFactory.drive_;
} }
@ -79,20 +79,7 @@ void Factory_init() {
ALIVE_setAliveTime(ALcontroller(), KART_CST.CONTROL_ALIVE_TIME); ALIVE_setAliveTime(ALcontroller(), KART_CST.CONTROL_ALIVE_TIME);
ALIVE_init(ALjoy()); ALIVE_init(ALjoy());
ALIVE_init(ALdrive()); DRIVE_init(drive());
}
void foo(void* p){
static int16_t speed = 0;
static bool up = true;
if(up) {
speed += 3;
if(speed >100) up = false;
} else {
speed -= 3;
if(speed < -100) up = true;
}
CM_DRIVE_POWER(&speed);
} }
//connect objects if required //connect objects if required
@ -110,31 +97,21 @@ void Factory_build() {
ALIVE_onBorn(ALjoy(), LED_on, l1()); ALIVE_onBorn(ALjoy(), LED_on, l1());
ALIVE_onDead(ALjoy(), LED_off, l1()); ALIVE_onDead(ALjoy(), LED_off, l1());
ALIVE_onSetup(ALdrive(), CM_DRIVE_SETUP, NULL); DRIVE_onRun(drive(), LED_on, l2());
ALIVE_setAliveTime(ALdrive(), KART_CST.DRIVE_ALIVE_TIME); DRIVE_onDead(drive(), LED_off, l2());
ALIVE_onBorn(ALdrive(), LED_on, l2());
ALIVE_onDead(ALdrive(), LED_off, l2());
BLINKER_setTimeOn(b1(), (KART_CST.DRIVE_STOP_TIME*9)/2);
BLINKER_setTimeOff(b1(), (KART_CST.DRIVE_STOP_TIME*9)/2);
BLINKER_onOn(b1(), foo, NULL);
} }
//start all state machines //start all state machines
void Factory_start() { void Factory_start() {
CAN_startBehaviour(); CAN_startBehaviour();
ALIVE_startBehaviourSender(ALcontroller()); //ALIVE_startBehaviourSender(ALcontroller());
ALIVE_startBehaviourChecker(ALjoy()); //ALIVE_startBehaviourChecker(ALjoy());
ALIVE_emitBorn(ALjoy(), 100, 0); ALIVE_emitBorn(ALjoy(), 100, 0);
ALIVE_emitReady(ALjoy(), 200, 0); ALIVE_emitReady(ALjoy(), 200, 0);
ALIVE_startBehaviourChecker(ALdrive());
ALIVE_emitBorn(ALdrive(), 100, 0);
ALIVE_emitReady(ALdrive(), 200, 0);
BLINKER_startBehaviour(b1()); DRIVE_startBehaviour(drive());
BLINKER_emitBlink(b1(), 300);
} }

View File

@ -15,6 +15,7 @@
#include "../car.h" #include "../car.h"
#include "../can_message.h" #include "../can_message.h"
#include "../eeprom.h" #include "../eeprom.h"
#include "../drive.h"
#include "../../board/led/led.h" #include "../../board/led/led.h"
#include "../../board/button/button.h" #include "../../board/button/button.h"
#include "../../middleware/alive.h" #include "../../middleware/alive.h"
@ -36,7 +37,7 @@ typedef struct {
ALIVE ALcontroller_; ALIVE ALcontroller_;
ALIVE ALjoy_; ALIVE ALjoy_;
ALIVE ALdrive_; DRIVE drive_;
} Factory; } Factory;
@ -59,7 +60,7 @@ BLINKER* b1();
ALIVE* ALcontroller(); ALIVE* ALcontroller();
ALIVE* ALjoy(); ALIVE* ALjoy();
ALIVE* ALdrive(); DRIVE* drive();
#endif #endif

View File

@ -10,6 +10,7 @@
<itemPath>app/can_message.h</itemPath> <itemPath>app/can_message.h</itemPath>
<itemPath>app/kartculator.h</itemPath> <itemPath>app/kartculator.h</itemPath>
<itemPath>app/eeprom.h</itemPath> <itemPath>app/eeprom.h</itemPath>
<itemPath>app/drive.h</itemPath>
</logicalFolder> </logicalFolder>
<logicalFolder name="board" displayName="board" projectFiles="true"> <logicalFolder name="board" displayName="board" projectFiles="true">
<itemPath>board/led/led.h</itemPath> <itemPath>board/led/led.h</itemPath>
@ -48,6 +49,7 @@
<itemPath>app/can_message.c</itemPath> <itemPath>app/can_message.c</itemPath>
<itemPath>app/kartculator.c</itemPath> <itemPath>app/kartculator.c</itemPath>
<itemPath>app/eeprom.c</itemPath> <itemPath>app/eeprom.c</itemPath>
<itemPath>app/drive.c</itemPath>
</logicalFolder> </logicalFolder>
<logicalFolder name="board" displayName="board" projectFiles="true"> <logicalFolder name="board" displayName="board" projectFiles="true">
<itemPath>board/led/led.c</itemPath> <itemPath>board/led/led.c</itemPath>

BIN
UML/drive.pdf Normal file

Binary file not shown.

137
UML/drive.uxf Normal file
View File

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<diagram program="umlet" version="15.0.0">
<zoom_level>15</zoom_level>
<element>
<id>Relation</id>
<coordinates>
<x>660</x>
<y>90</y>
<w>210</w>
<h>120</h>
</coordinates>
<panel_attributes>lt=-&gt;
evInit
/startAliveChecker
</panel_attributes>
<additional_attributes>10.0;10.0;10.0;60.0</additional_attributes>
</element>
<element>
<id>UMLSpecialState</id>
<coordinates>
<x>660</x>
<y>75</y>
<w>30</w>
<h>30</h>
</coordinates>
<panel_attributes>type=initial</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLState</id>
<coordinates>
<x>540</x>
<y>405</y>
<w>270</w>
<h>105</h>
</coordinates>
<panel_attributes>RUN
--
/entry: LED ON
--
emitPollTorqueEv</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>735</x>
<y>450</y>
<w>195</w>
<h>270</h>
</coordinates>
<panel_attributes>lt=-&gt;
m1= evPollTorque\n/sendTorque
</panel_attributes>
<additional_attributes>10.0;100.0;10.0;160.0;110.0;160.0;110.0;10.0;50.0;10.0</additional_attributes>
</element>
<element>
<id>UMLState</id>
<coordinates>
<x>495</x>
<y>180</y>
<w>360</w>
<h>135</h>
</coordinates>
<panel_attributes>WAIT
--
ALIVE_emitBorn(ALjoy(), 0, 0);
ALIVE_emitReady(ALjoy(), 100, 0);
setAliveTime</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>660</x>
<y>300</y>
<w>120</w>
<h>135</h>
</coordinates>
<panel_attributes>lt=-&gt;
m1=evStart\n(onWait)
</panel_attributes>
<additional_attributes>10.0;10.0;10.0;70.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>735</x>
<y>450</y>
<w>195</w>
<h>180</h>
</coordinates>
<panel_attributes>lt=-&gt;
m1= evPollSpeed\n/sendSpeed
</panel_attributes>
<additional_attributes>10.0;40.0;10.0;100.0;110.0;100.0;110.0;10.0;50.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>390</x>
<y>240</y>
<w>345</w>
<h>555</h>
</coordinates>
<panel_attributes>lt=-&gt;
m1= evResurrect\n(onBorn)
</panel_attributes>
<additional_attributes>130.0;300.0;130.0;350.0;10.0;350.0;10.0;10.0;70.0;10.0</additional_attributes>
</element>
<element>
<id>UMLState</id>
<coordinates>
<x>450</x>
<y>600</y>
<w>270</w>
<h>90</h>
</coordinates>
<panel_attributes>DEAD
--
/entry: LED OFF</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>570</x>
<y>495</y>
<w>135</w>
<h>135</h>
</coordinates>
<panel_attributes>lt=-&gt;
m1=evStop\n(onDead)
</panel_attributes>
<additional_attributes>10.0;10.0;10.0;70.0</additional_attributes>
</element>
</diagram>