diff --git a/F3:F303/MLX90640-allsky/Readme.md b/F3:F303/MLX90640-allsky/Readme.md index f0567ac..468e95b 100644 --- a/F3:F303/MLX90640-allsky/Readme.md +++ b/F3:F303/MLX90640-allsky/Readme.md @@ -7,7 +7,9 @@ thermal imaging sensors (32×24 pixels each), designed for **cloud monitoring** Astrophysical Observatory of the Russian Academy of Sciences. The system automates sky quality assessment for 0.5-meter telescopes of the "Astro-M" complex. -The device continuously captures thermal images from multiple sensors (Zenith, East, South, West, North), processes environmental data from a **BMP280** pressure/humidity/temperature sensor, and controls **PWM heaters** to prevent dew formation on optics. +The device continuously captures thermal images from multiple sensors (Zenith, East, South, West, +North), processes environmental data from a **BMP280** pressure/humidity/temperature sensor, and +controls **PWM heaters** to prevent dew formation on optics. **Repository:** [https://github.com/eddyem/stm32samples/tree/master/F3%3AF303/MLX90640-allsky](https://github.com/eddyem/stm32samples/tree/master/F3%3AF303/MLX90640-allsky) @@ -160,7 +162,8 @@ Measurements are triggered every `ENV_MEAS_PERIOD` (10 seconds) in forced mode. ## Command Protocol -The device presents a **virtual COM port** (CDC) over USB and a second UART interface. Both share the same command set. +The device presents a **virtual COM port** (CDC) over USB and a second UART interface. Both share +the same command set. ### Command Syntax ``` @@ -290,7 +293,9 @@ T_MEASUREMENT=12345678 ### Prerequisites - ARM GCC toolchain (`arm-none-eabi-gcc`) - Make -- [st-flash](https://github.com/texane/stlink), [stm32flash](https://sourceforge.net/projects/stm32flash/) or [OpenOCD](https://openocd.sourceforge.io) (for flashing MCU) +- [st-flash](https://github.com/texane/stlink), + [stm32flash](https://sourceforge.net/projects/stm32flash/) or + [OpenOCD](https://openocd.sourceforge.io) (for flashing MCU) ### Build ```bash diff --git a/F3:F303/MLX90640-allsky/adc.c b/F3:F303/MLX90640-allsky/adc.c index 1dc8689..c99570e 100644 --- a/F3:F303/MLX90640-allsky/adc.c +++ b/F3:F303/MLX90640-allsky/adc.c @@ -46,19 +46,20 @@ TRUE_INLINE void calADC(ADC_TypeDef *chnl){ chnl->CR = ADC_CR_ADVREGEN_0; // wait for 10us uint16_t ctr = 0; - while(++ctr < 1000){nop();} + while(++ctr < 1000){IWDG->KR = IWDG_REFRESH;} // ADCALDIF=0 (single channels) if((chnl->CR & ADC_CR_ADEN)){ chnl->CR |= ADC_CR_ADSTP; chnl->CR |= ADC_CR_ADDIS; } chnl->CR |= ADC_CR_ADCAL; - while((chnl->CR & ADC_CR_ADCAL) != 0 && ++ctr < 0xfff0){}; + while((chnl->CR & ADC_CR_ADCAL) != 0 && ++ctr < 0xfff0){IWDG->KR = IWDG_REFRESH;}; chnl->CR = ADC_CR_ADVREGEN_0; // enable ADC ctr = 0; do{ - chnl->CR |= ADC_CR_ADEN; + chnl->CR |= ADC_CR_ADEN; + IWDG->KR = IWDG_REFRESH; }while((chnl->ISR & ADC_ISR_ADRDY) == 0 && ++ctr < 0xfff0); } @@ -80,14 +81,16 @@ void adc_setup(){ ADC12_COMMON->CCR = ADC_CCR_TSEN | ADC_CCR_VREFEN | ADC_CCR_CKMODE; // enable Tsens and Vref, HCLK/4 calADC(ADC1); calADC(ADC2); - // ADC1: channels 1,2,3,4,16,18 - ADC1->SMPR1 = ADC_SMPR1_SMP0 | ADC_SMPR1_SMP1 | ADC_SMPR1_SMP2 | ADC_SMPR1_SMP3; - ADC1->SMPR2 = ADC_SMPR2_SMP15 | ADC_SMPR2_SMP17; + // ADC1: channels 1,2,3,4,16,18; 601.5 clock cycles + //ADC1->SMPR1 = ADC_SMPR1_SMP0 | ADC_SMPR1_SMP1 | ADC_SMPR1_SMP2 | ADC_SMPR1_SMP3; + ADC1->SMPR1 = ADC_SMPR1_SMP1 | ADC_SMPR1_SMP2 | ADC_SMPR1_SMP3 | ADC_SMPR1_SMP4; + //ADC1->SMPR2 = ADC_SMPR2_SMP15 | ADC_SMPR2_SMP17; + ADC1->SMPR2 = ADC_SMPR2_SMP16 | ADC_SMPR2_SMP18; // 6 conversions in group: 1->2->3->4->16->18 ADC1->SQR1 = (1<<6) | (2<<12) | (3<<18) | (4<<24) | (NUMBER_OF_ADC1_CHANNELS-1); ADC1->SQR2 = (16<<0) | (18<<6); // ADC2: channel 2 - ADC2->SMPR1 = ADC_SMPR1_SMP1; + ADC2->SMPR1 = ADC_SMPR1_SMP2; ADC2->SQR1 = (2<<6) | (NUMBER_OF_ADC2_CHANNELS-1); // configure DMA for ADC RCC->AHBENR |= RCC_AHBENR_DMA1EN | RCC_AHBENR_DMA2EN; @@ -122,12 +125,12 @@ void adc_setup(){ */ uint16_t getADCval(uint8_t nch){ if(nch >= NUMBER_OF_ADC_CHANNELS) return 0; - register uint16_t temp; + uint16_t temp; #define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); } #define PIX_SWAP(a,b) { temp=(a);(a)=(b);(b)=temp; } uint16_t p[9]; int adval = (nch >= NUMBER_OF_ADC1_CHANNELS) ? NUMBER_OF_ADC2_CHANNELS : NUMBER_OF_ADC1_CHANNELS; - int addr = (nch >= NUMBER_OF_ADC1_CHANNELS) ? nch - NUMBER_OF_ADC2_CHANNELS + ADC2START: nch; + int addr = (nch >= NUMBER_OF_ADC1_CHANNELS) ? nch - NUMBER_OF_ADC1_CHANNELS + ADC2START: nch; for(int i = 0; i < 9; ++i, addr += adval) // first we should prepare array for optmed p[i] = ADC_array[addr]; PIX_SORT(p[1], p[2]) ; PIX_SORT(p[4], p[5]) ; PIX_SORT(p[7], p[8]) ; diff --git a/F3:F303/MLX90640-allsky/allsky.bin b/F3:F303/MLX90640-allsky/allsky.bin index 202c9a8..b3e42d7 100755 Binary files a/F3:F303/MLX90640-allsky/allsky.bin and b/F3:F303/MLX90640-allsky/allsky.bin differ diff --git a/F3:F303/MLX90640-allsky/commproto.cpp b/F3:F303/MLX90640-allsky/commproto.cpp index 32e7326..8e80f04 100644 --- a/F3:F303/MLX90640-allsky/commproto.cpp +++ b/F3:F303/MLX90640-allsky/commproto.cpp @@ -595,9 +595,8 @@ static constexpr uint32_t hash(const char* str, uint32_t h = 0) { return *str ? hash(str + 1, h + ((h << 7) ^ *str)) : h; } - -const char *parse_cmd(int (*sendfun)(const char*), char *buf) { - if(!buf || !*buf || !sendfun) return NULL; +// set temporary sender +void set_sender(sendfun_t sendfun){ SEND = sendfun; if(sendfun == usb_sender){ putb = usb_putb; @@ -606,6 +605,15 @@ const char *parse_cmd(int (*sendfun)(const char*), char *buf) { putb = usart_putb; sendbin = usart_sendbin; } +} + +sendfun_t get_sender(){ + return SEND; +} + +const char *parse_cmd(sendfun_t sendfun, char *buf) { + if(!buf || !*buf || !sendfun) return NULL; + set_sender(sendfun); char command[CMD_MAXLEN+1]; int i = 0; while(*buf > '@' && i < CMD_MAXLEN) command[i++] = *buf++; diff --git a/F3:F303/MLX90640-allsky/commproto.h b/F3:F303/MLX90640-allsky/commproto.h index fc4d7ee..d68cbbc 100644 --- a/F3:F303/MLX90640-allsky/commproto.h +++ b/F3:F303/MLX90640-allsky/commproto.h @@ -49,10 +49,14 @@ typedef enum{ // maximal available parameter number (for 16-bit registers is 0xffff #define MAXPARNO 0xffff +typedef int (*sendfun_t)(const char*); + extern const char *EQ; -const char *parse_cmd(int (*sendfun)(const char*), char *buf); +const char *parse_cmd(sendfun_t sendfun, char *buf); void set_senders(int (*usbs)(const char*), int (*usbb)(uint8_t), int (*usbbin)(const uint8_t*, int), int (*usarts)(const char*), int (*usartb)(uint8_t), int (*usartbin)(const uint8_t*, int)); +void set_sender(sendfun_t sendfun); +sendfun_t get_sender(); extern const char *const Timage; diff --git a/F3:F303/MLX90640-allsky/i2c.c b/F3:F303/MLX90640-allsky/i2c.c index a6e822b..62bf3a4 100644 --- a/F3:F303/MLX90640-allsky/i2c.c +++ b/F3:F303/MLX90640-allsky/i2c.c @@ -116,6 +116,8 @@ void i2c_setup(i2c_speed_t speed){ RCC->AHBENR |= RCC_AHBENR_DMA1EN; NVIC_EnableIRQ(DMA1_Channel6_IRQn); NVIC_EnableIRQ(DMA1_Channel7_IRQn); + NVIC_SetPriority(DMA1_Channel6_IRQn, 3); + NVIC_SetPriority(DMA1_Channel7_IRQn, 3); I2Cbusy = 0; i2c_curspeed = speed; } @@ -153,7 +155,7 @@ static uint8_t waitISRbit(uint32_t bit, uint8_t isset){ } return 1; goterr: - I2C1->ICR = 0xff; + I2C1->ICR = 0x3f38; // clear all errors return 0; } diff --git a/F3:F303/MLX90640-allsky/ir-allsky.creator.user b/F3:F303/MLX90640-allsky/ir-allsky.creator.user index 4dd6952..288daa7 100644 --- a/F3:F303/MLX90640-allsky/ir-allsky.creator.user +++ b/F3:F303/MLX90640-allsky/ir-allsky.creator.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/F3:F303/MLX90640-allsky/main.c b/F3:F303/MLX90640-allsky/main.c index 4e6495a..7674096 100644 --- a/F3:F303/MLX90640-allsky/main.c +++ b/F3:F303/MLX90640-allsky/main.c @@ -83,16 +83,19 @@ int main(void){ usart_sendstr(foundid); usart_sendstr(straddr); usart_putbyte('\n'); } } + IWDG->KR = IWDG_REFRESH; mlx_process(); - if(cartoon) for(int i = 0; i < N_SENSORS; ++i){ // USB-only + if(cartoon && CDCready) for(int i = 0; i < N_SENSORS; ++i){ // USB-only uint32_t Tnow = mlx_lastimT(i); if(Tnow != Tlastima[i]){ fp_t *im = mlx_getimage(i); if(im){ - //U(Sensno); UN(i2str(i)); + sendfun_t cursender = get_sender(); + set_sender(USB_sendstr); U(Timage); USB_putbyte('0'+i); USB_putbyte('='); UN(u2str(Tnow)); drawIma(im); Tlastima[i] = Tnow; + set_sender(cursender); } } } diff --git a/F3:F303/MLX90640-allsky/mlx90640.c b/F3:F303/MLX90640-allsky/mlx90640.c index 73b3a76..c546eb6 100644 --- a/F3:F303/MLX90640-allsky/mlx90640.c +++ b/F3:F303/MLX90640-allsky/mlx90640.c @@ -43,7 +43,7 @@ static void occacc(int8_t *arr, int l, const uint16_t *regstart){ int n = l >> 2; // divide by 4 int8_t *p = arr; for(int i = 0; i < n; ++i){ - register uint16_t val = *regstart++; + uint16_t val = *regstart++; *p++ = (val & 0x000F) >> 0; *p++ = (val & 0x00F0) >> 4; *p++ = (val & 0x0F00) >> 8; @@ -123,7 +123,7 @@ MLX90640_params *get_parameters(const uint16_t dataarray[MLX_DMA_MAXLEN]){ int idx = (row&1)<<1; for(int col = 0; col < MLX_W; ++col){ // offset - register uint16_t rv = *pu16++; + uint16_t rv = *pu16++; i16 = (rv & 0xFC00) >> 10; if(i16 > 0x1F) i16 -= 0x40; *offset++ = (fp_t)offavg + (fp_t)occRow[row]*occRowScale + (fp_t)occColumn[col]*occColumnScale + (fp_t)i16*occRemScale; diff --git a/F3:F303/MLX90640-allsky/strfunc.c b/F3:F303/MLX90640-allsky/strfunc.c index 4d0009e..a9c086c 100644 --- a/F3:F303/MLX90640-allsky/strfunc.c +++ b/F3:F303/MLX90640-allsky/strfunc.c @@ -23,7 +23,7 @@ // hex line number for hexdumps void u16s(uint16_t n, char *buf){ for(int j = 3; j > -1; --j){ - register uint8_t q = n & 0xf; + uint8_t q = n & 0xf; n >>= 4; if(q < 10) buf[j] = q + '0'; else buf[j] = q - 10 + 'a'; @@ -40,7 +40,7 @@ void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len){ char buf[64] = "0000 ", *bptr = &buf[6]; for(uint16_t l = 0; l < len; ++l, ++arr){ for(int16_t j = 1; j > -1; --j){ - register uint8_t half = (*arr >> (4*j)) & 0x0f; + uint8_t half = (*arr >> (4*j)) & 0x0f; if(half < 10) *bptr++ = half + '0'; else *bptr++ = half - 10 + 'a'; } @@ -66,7 +66,7 @@ void hexdump16(int (*sendfun)(const char *s), uint16_t *arr, uint16_t len){ //uint16_t val = *arr; u16s(*arr, bptr); /*for(int16_t j = 3; j > -1; --j){ - register uint8_t q = val & 0xf; + uint8_t q = val & 0xf; val >>= 4; if(q < 10) bptr[j] = q + '0'; else bptr[j] = q - 10 + 'a'; @@ -297,8 +297,8 @@ const char *getint(const char *txt, int32_t *I){ int32_t sign = 1; uint32_t U; if(*s == '-'){ - sign = -1; - ++s; + sign = -1; + ++s; } const char *nxt = getnum(s, &U); if(nxt == s) return txt; @@ -341,7 +341,7 @@ char *float2str(float x, uint8_t prec){ uint8_t m = 0; if(pow < 0){pow = -pow; m = 1;} while(pow){ - register int p10 = pow/10; + int p10 = pow/10; *s-- = '0' + (pow - 10*p10); pow = p10; } @@ -355,7 +355,7 @@ char *float2str(float x, uint8_t prec){ uint32_t decimals = (uint32_t)((x-units+rounds[prec])*pwr10[prec]); // print decimals while(prec){ - register int d10 = decimals / 10; + int d10 = decimals / 10; *s-- = '0' + (decimals - 10*d10); decimals = d10; --prec; @@ -368,7 +368,7 @@ char *float2str(float x, uint8_t prec){ // print main units if(units == 0) *s-- = '0'; else while(units){ - register uint32_t u10 = units / 10; + uint32_t u10 = units / 10; *s-- = '0' + (units - 10*u10); units = u10; } diff --git a/F3:F303/MLX90640-allsky/usart.c b/F3:F303/MLX90640-allsky/usart.c index 8e766e0..2b64bab 100644 --- a/F3:F303/MLX90640-allsky/usart.c +++ b/F3:F303/MLX90640-allsky/usart.c @@ -149,8 +149,9 @@ int usart_setup(uint32_t speed){ NVIC_EnableIRQ(USART1_IRQn); NVIC_EnableIRQ(DMA1_Channel4_IRQn); NVIC_EnableIRQ(DMA1_Channel5_IRQn); - NVIC_SetPriority(DMA1_Channel5_IRQn, 0); - NVIC_SetPriority(USART1_IRQn, 4); // set character match priority lower + NVIC_SetPriority(DMA1_Channel4_IRQn, 4); + NVIC_SetPriority(DMA1_Channel5_IRQn, 4); + NVIC_SetPriority(USART1_IRQn, 5); // set character match priority lower return TRUE; } @@ -162,7 +163,7 @@ void usart_stop(){ void usart1_exti25_isr(){ DMA1_Channel5->CCR &= ~DMA_CCR_EN; // temporaly disable DMA USART1->ICR = USART_ICR_CMCF; // clear character match flag - register int l = UARTBUFSZI - DMA1_Channel5->CNDTR - 1; // substitute '\n' with '\0', omit empty strings! + int l = UARTBUFSZI - DMA1_Channel5->CNDTR - 1; // substitute '\n' with '\0', omit empty strings! if(l > 0){ if(recvdatalen){ // user didn't read old data - mark as buffer overflow bufovr = 1; diff --git a/F3:F303/MLX90640-allsky/version.inc b/F3:F303/MLX90640-allsky/version.inc index 80b70ea..6bc5225 100644 --- a/F3:F303/MLX90640-allsky/version.inc +++ b/F3:F303/MLX90640-allsky/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "67" -#define BUILD_DATE "2026-05-29" +#define BUILD_NUMBER "68" +#define BUILD_DATE "2026-06-01"