From 6409272876d59b82644824503fb42e3970940386 Mon Sep 17 00:00:00 2001 From: eddyem Date: Sat, 29 Dec 2018 21:03:26 +0300 Subject: [PATCH] add flowsensor & something more --- F0-nolib/Chiller/Readme.md | 19 ++++-- F0-nolib/Chiller/hardware.c | 74 ++++++++++++++++++++-- F0-nolib/Chiller/hardware.h | 6 ++ F0-nolib/Chiller/kicad/Chiller_control.pro | 42 ++---------- F0-nolib/Chiller/main.c | 12 ++-- F0-nolib/Chiller/protocol.c | 70 ++++++++++++++++++-- F0-nolib/Chiller/usart.c | 58 +++++++++++++---- F0-nolib/Chiller/usart.h | 1 + 8 files changed, 213 insertions(+), 69 deletions(-) diff --git a/F0-nolib/Chiller/Readme.md b/F0-nolib/Chiller/Readme.md index 618b590..97fce1e 100644 --- a/F0-nolib/Chiller/Readme.md +++ b/F0-nolib/Chiller/Readme.md @@ -9,13 +9,24 @@ Protocol: [ command line ] All messages are asynchroneous! Commands: -d - (only when EBUG defined) go into debug commands -R - reset MCU - +Ax - turn on(x=1)/off(x=0) external alarm or check its value +Cx - set cooler PWM to x +d - (only when EBUG defined) go into debug commands +F - get flow sensor rate for 5s period +Hx - set heater PWM to x +L - check water level sensor value +Px - set pump PWM to x +R - reset MCU +Tx - get NTC temperature for channel x +t - get MCU temperature +V - get Vdd value *100V Debugging commands: -w - test watchdog A - show raw ADC value (next letter is index, 0..5) +F - get flow_cntr value & PB state +T - show raw T values +w - test watchdog + Messages: MCUTEMP10=x - mcu temperature * 10 (degrC) diff --git a/F0-nolib/Chiller/hardware.c b/F0-nolib/Chiller/hardware.c index 9237ae9..205a66e 100644 --- a/F0-nolib/Chiller/hardware.c +++ b/F0-nolib/Chiller/hardware.c @@ -40,7 +40,6 @@ static inline void iwdg_setup(){ IWDG->KR = IWDG_REFRESH; /* (6) */ } - static inline void adc_setup(){ uint16_t ctr = 0; // 0xfff0 - more than 1.3ms // Enable clocking @@ -106,6 +105,7 @@ static inline void adc_setup(){ * PF0 - floating input - water level alert * PF1 - push-pull - external alarm * PA0..PA3 - ADC_IN0..3 + * PA4, PA6, PA7 - PWM outputs * Registers * MODER - input/output/alternate/analog (2 bit) * OTYPER - 0 pushpull, 1 opendrain @@ -119,20 +119,70 @@ static inline void adc_setup(){ */ static inline void gpio_setup(){ // Enable clocks to the GPIO subsystems - RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOFEN; - GPIOA->MODER = GPIO_MODER_MODER13_O | GPIO_MODER_MODER14_O | + RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOFEN; + GPIOA->MODER = + GPIO_MODER_MODER13_O | GPIO_MODER_MODER14_O | + GPIO_MODER_MODER4_AF | GPIO_MODER_MODER6_AF | + GPIO_MODER_MODER7_AF | GPIO_MODER_MODER0_AI | GPIO_MODER_MODER1_AI | GPIO_MODER_MODER2_AI | GPIO_MODER_MODER3_AI; - GPIOA->OTYPER = 3 << 13; // both opendrain + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // enable syscfg clock for EXTI + GPIOA->OTYPER = 3 << 13; // 13/14 opendrain GPIOF->MODER = GPIO_MODER_MODER1_O; + // PB1 - interrupt input + /* (2) Select Port B for pin 1 external interrupt by writing 0001 in EXTI1*/ + /* (3) Configure the corresponding mask bit in the EXTI_IMR register */ + /* (4) Configure the Trigger Selection bits of the Interrupt line on rising edge*/ + /* (5) Configure the Trigger Selection bits of the Interrupt line on falling edge*/ + SYSCFG->EXTICR[0] = SYSCFG_EXTICR1_EXTI1_PB; /* (2) */ + EXTI->IMR = EXTI_IMR_MR1; /* (3) */ + //EXTI->RTSR = 0x0000; /* (4) */ + EXTI->FTSR = EXTI_FTSR_TR1; /* (5) */ + /* (6) Enable Interrupt on EXTI0_1 */ + /* (7) Set priority for EXTI0_1 */ + NVIC_EnableIRQ(EXTI0_1_IRQn); /* (6) */ + NVIC_SetPriority(EXTI0_1_IRQn, 3); /* (7) */ + // alternate functions: + // PA4 - TIM14_CH1 (AF4) + // PA6 - TIM16_CH1 (AF5), PA7 - TIM17_CH1 (AF5) + GPIOA->AFR[0] = (GPIOA->AFR[0] &~ (GPIO_AFRL_AFRL4 | GPIO_AFRL_AFRL6 | GPIO_AFRL_AFRL7)) \ + | (4 << (4 * 4)) | (5 << (6 * 4)) | (5 << (7 * 4)); } static inline void timers_setup(){ - ; + // timer 14 ch1 - cooler PWM + // timer 16 ch1 - heater PWM + // timer 17 ch1 - pump PWM + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN; // enable clocking for timers 3 and 14 + RCC->APB2ENR |= RCC_APB2ENR_TIM16EN | RCC_APB2ENR_TIM17EN; // & timers 16/17 + // PWM mode 1 (active -> inactive) + TIM14->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; + TIM16->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; + TIM17->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; + // frequency + TIM14->PSC = 59; // 0.8MHz for 3kHz PWM + TIM16->PSC = 18749; // 2.56kHz for 10Hz PWM + TIM17->PSC = 5; // 8MHz for 31kHz PWM + // ARR for 8-bit PWM + TIM14->ARR = 254; + TIM16->ARR = 254; + TIM17->ARR = 254; + // start in OFF state + // TIM14->CCR1 = 0; and so on + // enable main output + TIM14->BDTR |= TIM_BDTR_MOE; + TIM16->BDTR |= TIM_BDTR_MOE; + TIM17->BDTR |= TIM_BDTR_MOE; + // enable PWM output + TIM14->CCER = TIM_CCER_CC1E; + TIM16->CCER = TIM_CCER_CC1E; + TIM17->CCER = TIM_CCER_CC1E; + // enable timers + TIM14->CR1 |= TIM_CR1_CEN; + TIM16->CR1 |= TIM_CR1_CEN; + TIM17->CR1 |= TIM_CR1_CEN; } - - void hw_setup(){ sysreset(); gpio_setup(); @@ -141,3 +191,13 @@ void hw_setup(){ USART1_config(); iwdg_setup(); } + +/* + * Flow sensor counter + */ +void exti0_1_isr(){ + if (EXTI->PR & EXTI_PR_PR1){ + EXTI->PR |= EXTI_PR_PR1; /* Clear the pending bit */ + ++flow_cntr; + } +} diff --git a/F0-nolib/Chiller/hardware.h b/F0-nolib/Chiller/hardware.h index f4323d3..6ee6882 100644 --- a/F0-nolib/Chiller/hardware.h +++ b/F0-nolib/Chiller/hardware.h @@ -20,6 +20,12 @@ #define HARDWARE_H #include "stm32f0.h" +// measure flow sensor data each 5 seconds +#define FLOW_RATE_MS 4999 +extern uint16_t flow_rate, flow_cntr; + +extern volatile uint32_t Tms; + void hw_setup(void); #endif // HARDWARE_H diff --git a/F0-nolib/Chiller/kicad/Chiller_control.pro b/F0-nolib/Chiller/kicad/Chiller_control.pro index 6940b87..8110c63 100644 --- a/F0-nolib/Chiller/kicad/Chiller_control.pro +++ b/F0-nolib/Chiller/kicad/Chiller_control.pro @@ -1,4 +1,4 @@ -update=Сб 17 ноя 2018 18:50:24 +update=Чт 20 дек 2018 22:32:48 version=1 last_client=kicad [pcbnew] @@ -25,43 +25,6 @@ version=1 NetIExt=net [general] version=1 -[eeschema] -version=1 -LibDir= -[eeschema/libraries] -LibName1=power -LibName2=device -LibName3=switches -LibName4=relays -LibName5=motors -LibName6=transistors -LibName7=conn -LibName8=linear -LibName9=regul -LibName10=74xx -LibName11=cmos4000 -LibName12=adc-dac -LibName13=memory -LibName14=xilinx -LibName15=microcontrollers -LibName16=dsp -LibName17=microchip -LibName18=analog_switches -LibName19=motorola -LibName20=texas -LibName21=intel -LibName22=audio -LibName23=interface -LibName24=digital-audio -LibName25=philips -LibName26=display -LibName27=cypress -LibName28=siliconi -LibName29=opto -LibName30=atmel -LibName31=contrib -LibName32=valves -LibName33=stm32 [schematic_editor] version=1 PageLayoutDescrFile= @@ -72,3 +35,6 @@ NetFmtName=Pcbnew SpiceForceRefPrefix=0 SpiceUseNetNumbers=0 LabSize=60 +[eeschema] +version=1 +LibDir= diff --git a/F0-nolib/Chiller/main.c b/F0-nolib/Chiller/main.c index f7b3dee..5f1f4fb 100644 --- a/F0-nolib/Chiller/main.c +++ b/F0-nolib/Chiller/main.c @@ -26,6 +26,8 @@ #include "protocol.h" volatile uint32_t Tms = 0; +uint16_t flow_rate = 0; // flow sensor rate +uint16_t flow_cntr = 0; // flow sensor trigger counter // Called when systick fires void sys_tick_handler(void){ @@ -33,7 +35,7 @@ void sys_tick_handler(void){ } int main(void){ -// uint32_t lastT = 0; + uint32_t lastTflow = 0; char *txt; hw_setup(); SysTick_Config(6000, 1); @@ -47,9 +49,11 @@ int main(void){ RCC->CSR |= RCC_CSR_RMVF; // remove reset flags while (1){ IWDG->KR = IWDG_REFRESH; - /*if(lastT > Tms || Tms - lastT > 499){ - lastT = Tms; - }*/ + if(Tms - lastTflow > FLOW_RATE_MS){ // onse per one second check flow sensor counter + lastTflow = Tms; + flow_rate = flow_cntr; + flow_cntr = 0; + } if(usart1_getline(&txt)){ // usart1 received command, process it txt = process_command(txt); }else txt = NULL; diff --git a/F0-nolib/Chiller/protocol.c b/F0-nolib/Chiller/protocol.c index 637bc4d..e988347 100644 --- a/F0-nolib/Chiller/protocol.c +++ b/F0-nolib/Chiller/protocol.c @@ -15,6 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include "hardware.h" #include "protocol.h" #include "usart.h" #include "adc.h" @@ -40,6 +41,14 @@ static void debugging_proc(const char *command){ } put_string("ADC value: "); put_uint(getADCval(i)); + put_string(", "); + usart1_sendbuf(); + break; + case 'F': + put_string("PB_IDR, flow_cntr: "); + put_uint(GPIOB->IDR); + put_string(", "); + put_uint(flow_cntr); usart1_sendbuf(); break; case 'T': // all raw T values @@ -70,7 +79,8 @@ static void get_ntc(const char *str){ } #define SEND(x) usart1_send_blocking(x, 0) - +#define STR(a) XSTR(a) +#define XSTR(a) #a /** * @brief process_command - command parser * @param command - command text (all inside [] without spaces) @@ -79,16 +89,66 @@ static void get_ntc(const char *str){ char *process_command(const char *command){ const char *ptr = command; char *ret = NULL; + int32_t N; usart1_sendbuf(); // send buffer (if it is already filled) switch(*ptr++){ case '?': // help - SEND("R - reset\nTx - get NTC temp\nt - get MCU temp\nV - get Vdd"); + SEND( + "Ax - alarm on(1)/off(0)\n" + "Cx - cooler PWM\n" + "F - get flow sensor rate for " STR(FLOW_RATE_MS) "ms\n" + "Hx - heater PWM\n" + "L - check water level\n" + "Px - pump PWM\n" + "R - reset\n" + "Tx - get NTC temp\n" + "t - get MCU temp\n" + "V - get Vdd" + ); #ifdef EBUG - SEND("d -> goto debug:"); - SEND("\tw - test watchdog\n\tAx - get raw ADCx value"); - SEND("\tT - show raw T values"); + SEND("d -> goto debug:\n" + "\tAx - get raw ADCx value\n" + "\tF - get flow_cntr\n" + "\tT - show raw T values\n" + "\tw - test watchdog" + ); #endif break; + case 'A': // turn alarm on/off + if(*ptr == '1') pin_set(GPIOF, 2); + else if(*ptr == '0')pin_clear(GPIOF, 2); + put_string("ALRM="); + put_char(pin_read(GPIOF, 2) + '0'); + break; + case 'C': // cooler PWM - TIM14CH1 + if(getnum(ptr, &N) && N > -1 && N < 256){ + TIM14->CCR1 = N; + } + put_string("COOLERPWM="); + put_int(TIM14->CCR1); + break; + case 'F': + put_string("FLOWRATE="); + put_uint(flow_rate); + break; + case 'H': // heater PWM - TIM16CH1 + if(getnum(ptr, &N) && N > -1 && N < 256){ + TIM16->CCR1 = N; + } + put_string("HEATERPWM="); + put_int(TIM16->CCR1); + break; + case 'L': // water level + put_string("WATERLEVEL="); + put_char('0' + pin_read(GPIOF, 1)); + break; + case 'P': // pump PWM - TIM17CH1 + if(getnum(ptr, &N) && N > -1 && N < 256){ + TIM17->CCR1 = N; + } + put_string("PUMPPWM="); + put_int(TIM17->CCR1); + break; case 'R': // reset MCU NVIC_SystemReset(); break; diff --git a/F0-nolib/Chiller/usart.c b/F0-nolib/Chiller/usart.c index 0584a6a..1ace7f3 100644 --- a/F0-nolib/Chiller/usart.c +++ b/F0-nolib/Chiller/usart.c @@ -34,10 +34,10 @@ static uint8_t linerdy = 0 // received data ready ; static int rbufno = 0; // current rbuf number -static char rbuf[2][UARTBUFSZ], tbuf[UARTBUFSZ]; // receive & transmit buffers +static char rbuf[2][UARTBUFSZ+1], tbuf[UARTBUFSZ]; // receive & transmit buffers static char *recvdata = NULL; -static char trbuf[UARTBUFSZ]; // auxiliary buffer for data transmission +static char trbuf[UARTBUFSZ+1]; // auxiliary buffer for data transmission static int trbufidx = 0; int put_char(char c){ @@ -161,18 +161,19 @@ void usart1_isr(){ } } switch(rb){ - case '[': - datalen[rbufno] = 0; - tmout = 0; - break; + case '[': + datalen[rbufno] = 0; + tmout = 0; + break; case ']': // close command - line ready! dlen = datalen[rbufno]; if(dlen){ - linerdy = 1; - incmd = 0; - recvdata = rbuf[rbufno]; - rbufno = !rbufno; - datalen[rbufno] = 0; + linerdy = 1; + incmd = 0; + recvdata = rbuf[rbufno]; + rbuf[rbufno][dlen] = 0; + rbufno = !rbufno; + datalen[rbufno] = 0; } tmout = 0; break; @@ -257,3 +258,38 @@ TXstatus usart1_send_blocking(const char *str, int len){ txrdy = 1; return ALL_OK; } + +// read `buf` and get first integer `N` in it +// @return pointer to first non-number if all OK or NULL if first symbol isn't a space or number +char *getnum(const char *buf, int32_t *N){ + char c; + int positive = -1; + int32_t val = 0; + //usart1_send_blocking(buf, 0); + while((c = *buf++)){ + if(c == '\t' || c == ' '){ + if(positive < 0) continue; // beginning spaces + else break; // spaces after number + } + if(c == '-'){ + if(positive < 0){ + positive = 0; + continue; + }else break; // there already was `-` or number + } + if(c < '0' || c > '9') break; + if(positive < 0) positive = 1; + val = val * 10 + (int32_t)(c - '0'); + } + if(positive != -1){ + if(positive == 0){ + if(val == 0) return NULL; // single '-' + val = -val; + } + *N = val; + }else return NULL; +/* usart1_sendbuf(); + put_uint(val); + put_char('\n');*/ + return (char*)buf-1; +} diff --git a/F0-nolib/Chiller/usart.h b/F0-nolib/Chiller/usart.h index 6a8c0bf..e4b7711 100644 --- a/F0-nolib/Chiller/usart.h +++ b/F0-nolib/Chiller/usart.h @@ -50,5 +50,6 @@ int put_string(const char *str); int put_int(int32_t N); int put_uint(uint32_t N); +char *getnum(const char *buf, int32_t *N); #endif // __USART_H__