Repositório para códigos do painel da plataforma SATC
Dependencies: MFRC522 mbed-STM32F103C8T6 mbed
Fork of C_005_EA_Painel_sem_bms by
main.cpp
00001 #include "main.h" 00002 /* 00003 192.168.0.59 00004 conta> pi 00005 senha> raspberry 00006 00007 Feito para placa MCA versao PECI091BA 00008 00009 Utiliza polling para afericao do estado dos botoes de acionamento frente/re 00010 utiliza polling para leitura do cartao 00011 00012 Funcionalidades: 00013 00014 Leitura de Cartao 00015 Botões: Frente/Re/Farol 00016 Acionamentos: KSI, Frente, Re, Farol 00017 00018 Codigo antecessor: C_005_DC 00019 Adicoes: 00020 Remocao da leitura de dados do bms 00021 00022 TO DO: 00023 00024 DONE: 00025 00026 00027 */ 00028 00029 00030 // Arrays que armazenam os estados dos botoes 00031 uint16_t in_frente_states[n_amostras]= {0}; 00032 uint16_t in_re_states[n_amostras]= {0}; 00033 uint16_t in_farol_states[n_amostras]= {0}; 00034 // contador utilizado para debounce, deixar os botoes impossivel de serem acionados 00035 uint8_t button_cooldown_counter = 0; 00036 00037 DigitalIn in_frente(PB_5); 00038 DigitalIn in_re(PB_6); 00039 DigitalIn in_farol(PB_7); 00040 DigitalIn in_freio_de_estacionamento(PB_4); 00041 00042 DigitalIn in_12v_charge_confirm(PB_10); 00043 00044 // Indicadores para o usuario 00045 PwmOut led_forward(PA_8); 00046 PwmOut led_backward(PA_9); 00047 PwmOut led_headlight(PA_11); 00048 PwmOut buzzer(PB_1); 00049 00050 DigitalOut embedded_led(PC_13); 00051 DigitalOut led_mobilis(PA_4); 00052 DigitalOut led_erro_3(PA_5); 00053 DigitalOut led_erro_2(PA_6); 00054 DigitalOut led_erro_1(PA_7); 00055 DigitalOut led_economia(PB_0); 00056 DigitalOut led_freio_est(PA_10); 00057 00058 DigitalInOut io_seta_e(PB_3); 00059 DigitalInOut io_seta_d(PA_15); 00060 00061 DigitalOut out_KSI(PA_1); 00062 DigitalOut out_frente(PA_2); 00063 DigitalOut out_re(PA_0); 00064 DigitalOut out_farol(PC_15); 00065 00066 volatile static CanStatus can_status = {true,true}; 00067 //struct que contem as falhas presentes no carro 00068 volatile static FalhasEAlarmes falhas_e_alarmes = {0,0,0,0,0}; 00069 // Struct que contem informacoes sobre o estado do Painel, ver arquivo 'main.h' 00070 volatile static Painel painel = {BUTTON_none,FAROL_off}; 00071 volatile uint16_t soc = 0; 00072 volatile uint16_t charge_current = 0; 00073 00074 bool car_is_on = false; 00075 bool car_is_locked = false; 00076 bool battery_is_charging = false; 00077 bool battery_is_charged = false; 00078 00079 // Timer utilizado para polling de botoes 00080 Ticker timer_botoes; 00081 CardReader rf_chip (PB_15, PB_14, PB_13, PB_12, PB_11); 00082 CAN can(PB_8,PB_9); 00083 00084 char arr_id_usuario[4] = {0,0,0,0}; 00085 00086 00087 00088 int main(void) 00089 { 00090 timer_botoes.attach(&checkButtons,button_polling_period); 00091 rf_chip.init(CRMODE_Polling); 00092 can.frequency(250000); 00093 can.attach(&getMsg); 00094 initPWMs(); 00095 turnOffSetup(); 00096 out_KSI = 0; 00097 wait_ms(500); 00098 00099 uint16_t T = 100; 00100 uint16_t k = 1; 00101 while(1){ 00102 // dt: tempo decorrido 00103 uint16_t dt = T*k; 00104 // a cada 100 ms : le cartao, liga/desliga carro de acordo 00105 if (dt%100 == 0){ 00106 if(!car_is_locked && rf_chip.readCard()){ 00107 if(rf_chip.cardIsValid()){ 00108 if(car_is_on){ 00109 tentaDesligarCarro(); 00110 }else{ 00111 tentaLigarCarro(); 00112 if(car_is_on){ 00113 k=1; 00114 } 00115 } 00116 }else{ 00117 //Caso cartao nao seja valido 00118 buzzWrongCard(); 00119 } 00120 }// nao faz nada caso nao haja cartao 00121 //processa botao apertado, caso haja 00122 if(car_is_on){ 00123 handlePressedButton(); 00124 } 00125 } 00126 // a cada 500ms: envia mensagens no can bus sobre alarme, falhas e estado dos acionamentos 00127 if(dt % 500 == 0){ 00128 if(car_is_on){ 00129 enviaEstadoDeAcionamentosFalhasEAlarmesViaCAN(); 00130 } 00131 } 00132 00133 // This routine is ran 00134 if(dt % 1000 == 0){ 00135 bool deve_travar_carro = in_12v_charge_confirm.read() == 1; 00136 if(deve_travar_carro){ 00137 if(car_is_on){ 00138 turnOffSetup(); 00139 out_KSI = 0; 00140 } 00141 // acende certo led 00142 car_is_on = false; 00143 car_is_locked = true; 00144 } 00145 bool deve_destravar_carro = car_is_locked && (in_12v_charge_confirm.read() == 0); 00146 if(deve_destravar_carro){ 00147 car_is_locked = false; 00148 // apaga certo led 00149 } 00150 00151 battery_is_charging = (in_12v_charge_confirm.read() == 1) && (charge_current > CHARGE_CURRENT_CHARGING); 00152 battery_is_charged = (in_12v_charge_confirm.read() == 1) && (charge_current < CHARGE_CURRENT_CHARGING); 00153 if(battery_is_charging){ 00154 led_mobilis = !led_mobilis; 00155 }else if(battery_is_charged){ 00156 led_mobilis = 1; 00157 }else if(!car_is_on){ 00158 led_mobilis = 0; 00159 } 00160 00161 int mensagem_enviada_sucesso = sendCanCarState(); 00162 afirmaFalha(!mensagem_enviada_sucesso, DTC_FALHA_CAN, &(falhas_e_alarmes.falha_mca)); 00163 } 00164 // a cada 5s: envia mensagem no can bus contendo id do usuario, 00165 if(dt % 5000 == 0){ 00166 if(car_is_on){ 00167 00168 char can_data_uid [4] = {0,0,0,0}; 00169 std::copy(arr_id_usuario, arr_id_usuario+ID_SIZE, can_data_uid); 00170 sendCanMsg(CAN_ID_id_usuario,can_data_uid,4); 00171 00172 // Checa se inversor e BMS estao se comunicando atraves das flags can_inversor_ok e can_bms_ok 00173 afirmaFalha(!can_status.can_inversor_ok, DTC_FALHA_INVERSOR_CAN, &falhas_e_alarmes.falha_mca); 00174 afirmaFalha(!can_status.can_bms_ok, DTC_FALHA_BMS_CAN, &falhas_e_alarmes.falha_mca); 00175 can_status.can_inversor_ok = false; 00176 can_status.can_bms_ok = false; 00177 00178 bool alarmes_existem = falhas_e_alarmes.alarme_mca || falhas_e_alarmes.alarme_weg; 00179 bool falhas_existem = falhas_e_alarmes.falha_mca || falhas_e_alarmes.falha_weg || falhas_e_alarmes.falha_bms; 00180 00181 led_erro_1 = falhas_existem; 00182 led_erro_2 = alarmes_existem; 00183 led_erro_3 = soc < SOC_BAIXA_CARGA; 00184 00185 } 00186 } 00187 // a cada 10 s: reseta leitor de cartoes 00188 if(dt > 10000){ 00189 int leitor_reset_sucesso = rf_chip.init(CRMODE_Polling); 00190 afirmaFalha(!leitor_reset_sucesso, DTC_FALHA_LEITOR, &falhas_e_alarmes.falha_mca); 00191 k=1; 00192 } 00193 k++; 00194 wait_ms(100); 00195 } 00196 } 00197 00198 /* Caso o flag acuse uma falha (com DTC 'DTC_da_falha'), registra ela no ponteiro *falha 00199 caso nao acuse falha, limpa essa falha do ponteiro *falha 00200 */ 00201 void afirmaFalha(int flag_not_ok, uint16_t DTC_da_falha, volatile uint16_t* falha){ 00202 if(flag_not_ok){ 00203 *falha = DTC_da_falha; 00204 }else if(*falha == DTC_da_falha){ 00205 *falha = 0; 00206 } 00207 } 00208 00209 // Executado ao passar o cartao quando carro esta' desligado 00210 void tentaLigarCarro(){ 00211 turnOnSetup(); 00212 car_is_on = true; 00213 // copia o cartao lido para array 'arr_id_usuario', que sera enviado pelo barramento CAN 00214 std::copy(rf_chip.last_valid_card, rf_chip.last_valid_card+ID_SIZE, arr_id_usuario); 00215 sendCanMsg(CAN_ID_id_usuario,arr_id_usuario,4); 00216 painel.pressed_button=BUTTON_none; 00217 } 00218 // Executado ao passar o cartao quando carro esta' ligado 00219 void tentaDesligarCarro(){ 00220 // Verifica se cartao lido e' o mesmo que foi utilizado para ligar o carro 00221 bool card_matches_previous = memcmp(rf_chip.last_valid_card, arr_id_usuario, sizeof(rf_chip.last_valid_card)) == 0; 00222 if(card_matches_previous){ 00223 turnOffSetup(); 00224 car_is_on = false; 00225 for(int i = 0; i < 15; i ++){ 00226 sendCanCarState(); 00227 wait_ms(1000); 00228 } 00229 out_KSI = 0; 00230 //Limpa informacao sobre id do usuario 00231 memset(arr_id_usuario, 0, sizeof(arr_id_usuario)); 00232 }else{ 00233 buzzWrongCard(); 00234 } 00235 } 00236 // Executado pelo main 00237 void enviaEstadoDeAcionamentosFalhasEAlarmesViaCAN(){ 00238 // Prepara arrays para envio 00239 char arr_falhas_e_alarmes[8]; 00240 populaArrayFalhasEAlarmes(arr_falhas_e_alarmes, 8); 00241 const uint8_t ARR_SIZE = 4; 00242 char arr_acionamentos[ARR_SIZE] = {out_frente.read(), out_re.read(), out_farol.read(), in_freio_de_estacionamento.read()}; 00243 // Envia as mensagens CAN 00244 sendCanMsg(CAN_ID_falhas_e_alarmes,arr_falhas_e_alarmes); 00245 sendCanMsg(CAN_ID_acionamentos,arr_acionamentos,ARR_SIZE); 00246 } 00247 00248 void populaArrayFalhasEAlarmes(char* array, size_t n){ 00249 // Arrays intermediarios para armazenar DTCs 00250 uint16_t can_falhas_array[2] = {0,0}; 00251 uint16_t can_alarmes_array[2] = {0,0}; 00252 if(falhas_e_alarmes.falha_mca != 0){ 00253 arrayPush(can_falhas_array, falhas_e_alarmes.falha_mca, 2); 00254 } 00255 if(falhas_e_alarmes.falha_bms != 0){ 00256 arrayPush(can_falhas_array, falhas_e_alarmes.falha_bms, 2); 00257 } 00258 if(falhas_e_alarmes.falha_weg != 0){ 00259 arrayPush(can_falhas_array, falhas_e_alarmes.falha_weg, 2); 00260 } 00261 if(falhas_e_alarmes.alarme_mca != 0){ 00262 arrayPush(can_alarmes_array, falhas_e_alarmes.alarme_mca, 2); 00263 } 00264 if(falhas_e_alarmes.alarme_weg != 0){ 00265 arrayPush(can_alarmes_array, falhas_e_alarmes.alarme_weg, 2); 00266 } 00267 char array_preparado[] = {can_falhas_array[0]&0xFF, can_falhas_array[0]>>8, can_falhas_array[1]&0xFF, can_falhas_array[1]>>8, 00268 can_alarmes_array[0]&0xFF, can_alarmes_array[0]>>8, can_alarmes_array[1]&0xFF, can_alarmes_array[1]>>8}; 00269 std::copy(array_preparado,array_preparado+8, array); 00270 } 00271 ////////////////////// BEGIN CAN ///////////////////////////////////////////// 00272 /* Funcao chamada sempre que uma mensagem chega no barramento CAN 00273 obs: Roda concorrentemente com o main!!! 00274 */ 00275 00276 int sendCanCarState(){ 00277 00278 char estados_do_carro[8] = {car_is_on, !car_is_on, in_12v_charge_confirm.read(), battery_is_charging, battery_is_charged, 0x00, 0x00, 0x00}; 00279 return sendCanMsg(CAN_ID_ESTADO_DO_CARRO,estados_do_carro); 00280 } 00281 00282 void getMsg(){ 00283 CANMessage msg; 00284 if(!can.read(msg)){ 00285 return; 00286 } 00287 switch(msg.id){ 00288 case CAN_ID_WEG_FALHAS_E_ALARMES: 00289 falhas_e_alarmes.falha_weg = converteDTCWeg(msg.data[1]<<8 | msg.data[0]); 00290 falhas_e_alarmes.alarme_weg = converteDTCWeg(msg.data[3]<<8 | msg.data[2]); 00291 can_status.can_inversor_ok = true; 00292 break; 00293 case CAN_ID_BMS_FALHAS_E_ALARMES: 00294 falhas_e_alarmes.falha_bms = converteDTCBms(msg.data[5]<<8 | msg.data[4]); 00295 can_status.can_bms_ok = true; 00296 break; 00297 case CAN_ID_BMS_SOC: 00298 { // Chaves utilizadas para que consigamos declarar variaveis dentro de um 'case' 00299 soc = msg.data[7]<<8 | msg.data[6]; 00300 charge_current = msg.data[3] << 8 | msg.data[2]; 00301 bool falha_no_circ_de_carga = (soc < 50) && (charge_current < CHARGE_CURRENT_CHARGING) && (falhas_e_alarmes.falha_bms == 0) && (in_12v_charge_confirm.read() == 1); 00302 afirmaFalha(falha_no_circ_de_carga, DTC_FALHA_CIRCUITO_DE_CARGA, &falhas_e_alarmes.falha_mca); 00303 } 00304 break; 00305 case CAN_ID_WEG_SENTIDO_DE_MOVIMENTO: 00306 { 00307 bool frente_inv = msg.data[0]; 00308 bool re_inv = msg.data[2]; 00309 bool divergencia = frente_inv != out_frente.read() || re_inv != out_re.read(); 00310 afirmaFalha(divergencia, DTC_FALHA_DIVERGENCIA_ENTRE_ACIONAMENTOS, &falhas_e_alarmes.falha_mca); 00311 } 00312 break; 00313 default: 00314 break; 00315 } 00316 } 00317 00318 // funcao para envio de mensagem pelo barramento CAN 00319 int sendCanMsg(int id, const char *data, char len, CANType type, CANFormat format) 00320 { 00321 if(can.tderror() != 0 || can.rderror() != 0){ 00322 can.frequency(250000); 00323 can.attach(&getMsg); 00324 } 00325 int msgSent = can.write(CANMessage(id,data,len,type,format)); 00326 return msgSent; 00327 } 00328 ///////////////////////// END CAN /////////////////////////// 00329 00330 ///////////////////////// BEGIN STANDARD IO ////////////////////////// 00331 // Funcao que processa o botao apertado 00332 void handlePressedButton(){ 00333 //ignora botao apertado caso tenha pouco tempo que um botao tenha sido apertado 00334 if(button_cooldown_counter > 0 ){ 00335 painel.pressed_button= BUTTON_none; 00336 button_cooldown_counter --; 00337 } 00338 bool estado_mudou = setLedsAndRelays(painel.pressed_button); 00339 if(estado_mudou){ 00340 beepBuzzer(100); 00341 } 00342 // inicializa contador caso botao tenha sido apertado 00343 if(painel.pressed_button != BUTTON_none){ 00344 button_cooldown_counter = BUTTON_COOLDOWN_COUNTER_RESET; 00345 } 00346 painel.pressed_button= BUTTON_none; 00347 } 00348 00349 /* rotina executada sempre que o carro liga: 00350 Aciona KSI, 00351 Pisca todos os LEDS, 00352 Aciona buzzer por 100 ms 00353 */ 00354 void turnOnSetup(){ 00355 out_KSI = 1; 00356 out_frente = 0; 00357 out_re = 0; 00358 out_farol = 0; 00359 00360 io_seta_e.output(); 00361 io_seta_d.output(); 00362 00363 led_mobilis = 1; 00364 led_erro_3 = 1; 00365 led_erro_2=1; 00366 led_erro_1 =1; 00367 led_economia =1; 00368 led_freio_est=1; 00369 io_seta_e = 1; 00370 io_seta_d = 1; 00371 00372 led_forward.write(led_max); 00373 led_backward.write(led_max); 00374 led_headlight.write(led_max); 00375 00376 beepBuzzer(100); 00377 wait_ms(300); 00378 00379 led_erro_3 = 0; 00380 led_erro_2=0; 00381 led_erro_1 =0; 00382 led_economia =0; 00383 led_freio_est=0; 00384 io_seta_e = 0; 00385 io_seta_d = 0; 00386 led_forward.write(led_weak); 00387 led_backward.write(led_weak); 00388 led_headlight.write(led_weak); 00389 io_seta_e.input(); 00390 io_seta_d.input(); 00391 wait_ms(200); 00392 } 00393 00394 00395 /* rotina executada sempre que o carro desliga: 00396 Desaciona todos os acionamentos, 00397 Pisca todos os LEDS, 00398 Aciona buzzer por 100 ms 00399 espera 200 ms 00400 Aciona buzzer por 50 ms 00401 */ 00402 void turnOffSetup(){ 00403 io_seta_e.output(); 00404 io_seta_d.output(); 00405 out_frente = 0; 00406 out_re = 0; 00407 out_farol = 0; 00408 led_mobilis = 1; 00409 led_erro_3 = 1; 00410 led_erro_2=1; 00411 led_erro_1 =1; 00412 led_economia =1; 00413 led_freio_est=1; 00414 io_seta_e = 1; 00415 io_seta_d = 1; 00416 led_forward.write(led_max); 00417 led_backward.write(led_max); 00418 led_headlight.write(led_max); 00419 00420 beepBuzzer(100); 00421 wait_ms(300); 00422 led_forward.write(0); 00423 led_backward.write(0); 00424 led_headlight.write(0); 00425 led_mobilis = 0; 00426 led_erro_3 = 0; 00427 led_erro_2=0; 00428 led_erro_1 =0; 00429 led_economia =0; 00430 led_freio_est=0; 00431 io_seta_e = 0; 00432 io_seta_d = 0; 00433 io_seta_e.input(); 00434 io_seta_d.input(); 00435 wait_ms(200); 00436 beepBuzzer(50); 00437 wait_ms(500); 00438 } 00439 00440 // Acende leds e aciona reles de acordo com o botao apertado 00441 bool setLedsAndRelays(PainelButton button){ 00442 bool buzz = true; 00443 switch (button){ 00444 case BUTTON_forward: 00445 led_forward.write(D_ON_LED_FRENTE_RE); 00446 led_backward.write(D_OFF_LED_FRENTE_RE); 00447 out_frente = 1; 00448 out_re = 0; 00449 break; 00450 case BUTTON_backward: 00451 led_forward.write(D_OFF_LED_FRENTE_RE); 00452 led_backward.write(D_ON_LED_FRENTE_RE); 00453 out_frente = 0; 00454 out_re = 1; 00455 break; 00456 case BUTTON_headlights: 00457 if(painel.farol == FAROL_on){ 00458 led_headlight.write(D_OFF_LED_HEADLIGHT); 00459 painel.farol = FAROL_off; 00460 io_seta_e = 1; 00461 out_farol = 0; 00462 }else{ 00463 led_headlight.write(D_ON_LED_HEADLIGHT); 00464 painel.farol = FAROL_on; 00465 out_farol = 1; 00466 } 00467 break; 00468 case BUTTON_none: 00469 default: 00470 buzz = false; 00471 break; 00472 } 00473 return buzz; 00474 } 00475 00476 // Configura o periodo das saidas PWM 00477 void initPWMs(){ 00478 led_forward.period_ms(leds_pwm_period); 00479 led_backward.period_ms(leds_pwm_period); 00480 led_headlight.period_ms(leds_pwm_period); 00481 buzzer.period_us(buzzer_period_us); 00482 } 00483 00484 // Acionamento do buzzer 00485 void beepBuzzer(int ms_duration){ 00486 buzzer.write(D_BUZZER_STD); 00487 wait_ms(ms_duration); 00488 buzzer.write(0); 00489 } 00490 00491 void buzzWrongCard(){ 00492 beepBuzzer(100); 00493 wait_ms(100); 00494 beepBuzzer(100); 00495 wait_ms(100); 00496 beepBuzzer(100); 00497 } 00498 00499 00500 /* 00501 Funcao acionada a cada 'button_polling_period' milissegundos em concorrencia com o main 00502 Se das ultimas 'n_amostras' de afericao de um botao, 00503 pelo menos 'button_treshold' delas tiverem sido verdadeiras, 00504 Considera botao como apertado 00505 Algoritmo: 00506 Le o estado do botao 00507 Empurra esse estado num array 00508 Caso a soma dos elementos desse array for maior que 'button_treshold' 00509 e caso o acionamento nao esteja acionado (valido para frente/re): 00510 considera botao como apertado 00511 */ 00512 void checkButtons(){ 00513 int frente_state = in_frente.read(); 00514 arrayPush(in_frente_states, frente_state, n_amostras); 00515 bool frente_pressionado = arraySum(in_frente_states,n_amostras) > button_treshold; 00516 int re_state = in_re.read(); 00517 arrayPush(in_re_states,re_state,n_amostras); 00518 bool re_pressionado = arraySum(in_re_states,n_amostras) > button_treshold; 00519 if(re_pressionado && frente_pressionado) 00520 { 00521 painel.pressed_button = BUTTON_none; 00522 }else if(frente_pressionado && (out_frente.read() != 1)) 00523 { 00524 painel.pressed_button = BUTTON_forward; 00525 }else if(re_pressionado && (out_re.read() != 1)) 00526 { 00527 painel.pressed_button = BUTTON_backward; 00528 } 00529 int farol_state = in_farol.read(); 00530 arrayPush(in_farol_states,farol_state,n_amostras); 00531 if(arraySum(in_farol_states,n_amostras)> button_treshold){ 00532 painel.pressed_button = BUTTON_headlights; 00533 } 00534 } 00535 00536 /////////////////////// END STANDARD IO ////////////////////////////////////
Generated on Wed Jul 13 2022 23:43:00 by
1.7.2
