6 * @author Bc. Jiri Kubias, jiri.kubias@gmail.com
13 * @defgroup lift Lift application
15 * Lift control application
16 * - controlls the lift and pusher
17 * - program recieves CAN commands about wanted lift/pusher position
18 * - also controls Holded and right chelae
26 ////////////////////////////////////////////////////////////////////////////////
28 // Eurobot BLINK TEST (with LPC2129)
32 // This software control mechanisms in eurobot. Use it with lpceurobot board
33 // Author : Jarda Sach DCE CVUT
36 ////////////////////////////////////////////////////////////////////////////////
38 #include <lpc21xx.h> /* LPC21xx definitions */
41 #include <system_def.h>
43 #include <periph/can.h>
53 #include <can_msg_def.h>
60 struct fsm fsm_pusher;
63 void CAN_rx(can_msg_t *msg);
67 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
68 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72 void init_motors(void){
74 init_engine_A(); // initialization of PWM unit
76 engine_A_en(ENGINE_EN_ON); //enable motor A
77 engine_B_en(ENGINE_EN_ON); // ----//----- B
78 engine_A_dir(ENGINE_DIR_FW); //set direction
79 engine_B_dir(ENGINE_DIR_FW);
80 engine_A_pwm(0); // STOP pwm is in percent, range 0~100~200
81 engine_B_pwm(0); // STOP pwm is in percent, range 0~100~200
85 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
86 void set_irq_handler(uint8_t source, uint8_t irq_vect, void (*handler)()) {
87 /* set interrupt vector */
88 ((uint32_t*)&VICVectAddr0)[irq_vect] = (uint32_t)handler;
89 ((uint32_t*)&VICVectCntl0)[irq_vect] = 0x20 | source;
90 /* enable interrupt */
91 VICIntEnable = 1<<source;
94 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97 void timer0_irq() __attribute__((interrupt));
98 volatile uint32_t timer_msec = 0, timer_usec = 0;
100 void init_timer0(uint32_t prescale, uint32_t period) {
101 T0TCR = 0x2; /* reset */
104 T0MCR = 0x3; /* match0: reset & irq */
105 T0EMR = 0; /* no ext. match */
106 T0CCR = 0x0; /* no capture */
107 T0TCR = 0x1; /* go! */
111 static unsigned cnt1khz = 0;
113 /* reset timer irq */
116 /* read IRCs @100kHz */
118 /* increment timer_usec */
120 /* increment msec @1kHz */
121 if (++cnt1khz == 100) {
126 /* int acknowledge */
132 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
133 void init_periphery(void){
135 can_init_baudrate(CAN_SPEED, CAN_ISR, CAN_rx);//initialization of CAN bus
137 init_servo(SERVO_PRIORITY);//SERVO_PRIORITY is level of intrrupt, is defined in lift header file
138 set_servo(SERVO_DOOR, SERVO_DOOR_MAX);
139 set_servo(CHELAE_R, CHELAE_R_MAX);
142 init_timer0(1, CPU_APB_HZ/100000);
143 set_irq_handler(4 /*timer0*/, IRC_PRIORITY, timer0_irq);
150 /*********************************************************/
151 void can_send_status(void)
154 if (fsm_lift.ans_can == 0x118)
155 send_rs_str("WRONG!!!\n");
156 tx_msg.id = CAN_LP_STATUS;
159 tx_msg.data[0] = (fsm_pusher.ans_can >> 8) & 0xFF;
160 tx_msg.data[1] = fsm_pusher.ans_can & 0xFF;
161 tx_msg.data[2] = (fsm_lift.ans_can >> 8) & 0xFF;
162 tx_msg.data[3] = fsm_lift.ans_can & 0xFF;
163 tx_msg.data[4] = can_flags;
164 while(can_tx_msg(&tx_msg)); /* CAN erratum workaround */
167 void can_send_len(void)
170 tx_msg.id = CAN_LP_STATUS;
173 tx_msg.data[0] = (fsm_pusher.lenght >> 8) & 0xFF;
174 tx_msg.data[1] = fsm_pusher.lenght & 0xFF;
175 tx_msg.data[2] = (fsm_lift.lenght >> 8) & 0xFF;
176 tx_msg.data[3] = fsm_lift.lenght & 0xFF;
177 while(can_tx_msg(&tx_msg));
182 void can_send_db(void)
185 tx_msg.id = CAN_DB_LP;
188 tx_msg.data[0] = (fsm_pusher.act_pos >> 8) & 0xFF;
189 tx_msg.data[1] = fsm_pusher.act_pos & 0xFF;
190 tx_msg.data[2] = (fsm_lift.act_pos >> 8) & 0xFF;
191 tx_msg.data[3] = fsm_lift.act_pos & 0xFF;
192 while(can_tx_msg(&tx_msg));
196 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197 void CAN_rx(can_msg_t *msg) {
200 memcpy(&rx_msg, msg, sizeof(can_msg_t));//make copy of message
208 req = ((rx_msg.data[0]<<8) | (rx_msg.data[1]));
210 fsm_lift.can_req_position = req;// save new req position of lift
214 req = ((rx_msg.data[0]<<8) | (rx_msg.data[1]));
215 fsm_pusher.can_req_position = req;// save new req position of lift
220 set_servo(SERVO_DOOR, SERVO_DOOR_MIN + (0xFF -rx_msg.data[0]) * (SERVO_DOOR_MAX - SERVO_DOOR_MIN)/255 ); //set servo position TODO: limits
225 set_servo(CHELAE_R , CHELAE_R_MIN + (0xFF - rx_msg.data[1]) * (CHELAE_R_MAX - CHELAE_R_MIN)/255 ); //set servo position TODO: limits
233 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
234 void run_fsm(struct fsm *fsm){
236 fsm->last_state = fsm->current_state; // set actual state
237 fsm->current_state(fsm, EVENT_DO); // change parameter
239 if(fsm->last_state != fsm->current_state){ // if state was changed
240 fsm->last_state(fsm, EVENT_EXIT); // finish the old state
241 fsm->current_state(fsm, EVENT_ENTRY); // initialize the new state
246 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
247 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
248 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
251 // ~~~~~ initialization of periphery ~~~~~
256 fsm_pusher.type = FSM_PUSHER;
257 fsm_lift.type = FSM_LIFT;
259 fsm_lift.current_state = &fsm_init;
260 fsm_pusher.current_state = &fsm_init;
261 fsm_lift.current_state(&fsm_lift, EVENT_ENTRY);
262 fsm_pusher.current_state(&fsm_pusher, EVENT_ENTRY);
264 uint32_t main_time = timer_usec;
265 uint32_t led_time = timer_msec;
266 uint32_t CAN_time = timer_msec;
268 SET_PIN(PINSEL1, 1, PINSEL_0);
269 SET_PIN(PINSEL1, 3, PINSEL_0);
276 // if(IO1PIN & (1<<20))
279 // deb_led_off(LEDY);
282 // if(IO1PIN & (1<<21))
285 // deb_led_off(LEDR);
289 send_rs_str("list started\n");
294 if(timer_usec >= main_time + 1000)
296 main_time = timer_usec;
298 run_fsm(&fsm_pusher);
300 fsm_lift.switch_front = (0 != (IO1PIN & (1<<LIFT_FRONT_SWITCH)));
301 fsm_lift.switch_back = (0 != (IO1PIN & (1<<LIFT_BACK_SWITCH)));
303 static int counter = 0;
304 /* Histereze koncaku */
305 if (0 != (IO1PIN & (1<<PUSHER_FRONT_SWITCH))) counter++;
309 fsm_pusher.switch_front = true;
312 fsm_pusher.switch_front = false;
316 fsm_pusher.switch_back = (0 != (IO1PIN & (1<<PUSHER_BACK_SWITCH)));
318 if (fsm_lift.switch_front) can_flags |= LIFT_LIFT_ENDSW_UP;
319 else can_flags &= ~LIFT_LIFT_ENDSW_UP;
320 if (fsm_lift.switch_back) can_flags |= LIFT_LIFT_ENDSW_DOWN;
321 else can_flags &= ~LIFT_LIFT_ENDSW_DOWN;
323 if (fsm_pusher.switch_front) can_flags |= LIFT_PUSHER_ENDSW_FW;
324 else can_flags &= ~LIFT_PUSHER_ENDSW_FW;
325 if (fsm_pusher.switch_back) can_flags |= LIFT_PUSHER_ENDSW_BK;
326 else can_flags &= ~LIFT_PUSHER_ENDSW_BK;
331 if (timer_msec >= CAN_time + 100){ //repeat sending message every 100 ms
332 CAN_time = timer_msec; //save new time, when message was sent
336 if(timer_msec >= led_time + 500)
338 led_time = timer_msec;
339 deb_led_change(LEDG);