diff --git a/schematic/ALL.pro b/schematic/ALL.pro index 3503ec5..0341989 100644 --- a/schematic/ALL.pro +++ b/schematic/ALL.pro @@ -1,6 +1,6 @@ -update=Ср 16 июл 2014 14:03:06 +update=Ср 01 апр 2015 19:30:22 version=1 -last_client=pcbnew +last_client=kicad [cvpcb] version=1 NetIExt=net @@ -54,11 +54,13 @@ LibName34=vreg LibName35=open-project [pcbnew] version=1 +PageLayoutDescrFile= LastNetListRead=ALL.net UseCmpFile=1 -PadDrill=0 -PadSizeH=2 -PadSizeV=2.5 +PadDrill=0.7999999999999999 +PadDrillOvalY=0.7999999999999999 +PadSizeH=1.5 +PadSizeV=2 PcbTextSizeV=1.5 PcbTextSizeH=1.5 PcbTextThickness=0.3 @@ -70,30 +72,3 @@ SolderMaskMinWidth=0 DrawSegmentWidth=0.4 BoardOutlineThickness=0.3 ModuleOutlineThickness=0.3 -[pcbnew/libraries] -LibDir=/home/eddy/kicad;/home/eddy/kicad/CYB3R_from_LOR/kicad;/home/eddy/kicad/Kicad-Libraries/modules;/home/eddy/kicad/kicadlibrary;mod -LibName1=sockets -LibName2=connect -LibName3=discret -LibName4=pin_array -LibName5=divers -LibName6=libcms -LibName7=display -LibName8=led -LibName9=dip_sockets -LibName10=pga_sockets -LibName11=valves -LibName12=open-project -LibName13=dip -LibName14=pinhead -LibName15=pinhead-double -LibName16=pinhead-double-smd -LibName17=qfp -LibName18=smd -LibName19=sot -LibName20=quartz -LibName21=w_crystal -LibName22=capacitors -LibName23=gprm1-45-61 -LibName24=my_modules -LibName25=smd_diodes diff --git a/with_opencm3/flash.c b/with_opencm3/flash.c index 8fc7355..4d080e4 100644 --- a/with_opencm3/flash.c +++ b/with_opencm3/flash.c @@ -23,7 +23,12 @@ #include #include -const flash_data Stored_Data __attribute__ ((aligned(FLASH_BLOCK_SIZE))) = { +// this is variable structure saved in RAM for ability of data changing +stored_data Stored_Data; + +// this is constant structure saved in flash. It have to be copied to Stored_Data after run +const flash_data Flash_Data __attribute__ ((aligned(FLASH_BLOCK_SIZE))) = { +.all_stored = { //.magick = FLASH_MAGICK, ._ADC_multipliers = {100000,100000,100000,100000,100000,100000,100000,100000, // TRD 26, // shutter @@ -33,12 +38,13 @@ const flash_data Stored_Data __attribute__ ((aligned(FLASH_BLOCK_SIZE))) = { 25, // shutter 7 // power } +} }; -uint32_t flash_write_data(uint32_t *dataptr, uint16_t datalen){ - uint32_t start_address = (uint32_t)&Stored_Data; +uint8_t flash_write_data(uint32_t *dataptr, uint16_t datalen){ + uint32_t start_address = (uint32_t)&(Flash_Data.all_stored); uint16_t i, rem; - uint32_t ret = 0; + uint8_t ret = 0; flash_unlock(); DBG("erase\n"); //Erasing page @@ -76,14 +82,18 @@ endoffunction: return ret; } -uint32_t flash_store_U32(uint32_t addr, uint32_t *data){ - flash_data Saved_Data; - uint32_t sz, ptrdiff; - sz = (uint32_t)&Stored_Data.last_addr - (uint32_t)&Stored_Data; - ptrdiff = addr - (uint32_t)&Stored_Data; - memcpy((void*)&Saved_Data, (void*)&Stored_Data, sz); - memcpy((void*)((uint32_t)&Saved_Data + ptrdiff), (void*)data, 4); - return flash_write_data((uint32_t*)&Saved_Data, sz); +/** + * save all data from RAM to flash + */ +uint8_t save_flashdata(){ +// uint32_t sz = (uint32_t)&Stored_Data.last_addr - (uint32_t)&Stored_Data; + //return flash_write_data((uint32_t*)&Stored_Data, sz); + return flash_write_data((uint32_t*)&Stored_Data, sizeof(stored_data)); +} + +void read_stored_data(){ +// uint32_t sz = (uint32_t)&Stored_Data.last_addr - (uint32_t)&Stored_Data; + memcpy((void*)&Stored_Data, (void*)&(Flash_Data.all_stored), sizeof(stored_data)); } /** @@ -96,12 +106,12 @@ void dump_flash_data(sendfun s){ P("\nADC multipliers: ", s); for(i = 0; i < ADC_CHANNELS_NUMBER; i++){ if(i) P(", ", s); - print_int(ADC_multipliers[i], s); + print_int(Flash_Data.all_stored._ADC_multipliers[i], s); } P("\nADC divisors: ", s); for(i = 0; i < ADC_CHANNELS_NUMBER; i++){ if(i) P(", ", s); - print_int(ADC_divisors[i], s); + print_int(Flash_Data.all_stored._ADC_divisors[i], s); } s('\n'); } diff --git a/with_opencm3/flash.h b/with_opencm3/flash.h index 8e23186..f10677a 100644 --- a/with_opencm3/flash.h +++ b/with_opencm3/flash.h @@ -32,7 +32,7 @@ * align by 2k & make size 2k for using with high density devices */ #define FLASH_BLOCK_SIZE (2048) -#define FLASH_WRONG_DATA_WRITTEN 0x80 +#define FLASH_WRONG_DATA_WRITTEN ((uint8_t)0x80) #define FLASH_MAGICK ((uint32_t) 0xAA55A55A) @@ -41,16 +41,21 @@ typedef struct{ // A-D value[x] = ADU * ADC_multipliers[x] / ADC_divisors[x] uint32_t _ADC_multipliers[ADC_CHANNELS_NUMBER]; uint32_t _ADC_divisors[ADC_CHANNELS_NUMBER]; - char last_addr[0]; // we need this pointer to calculate real size of structure +// char last_addr[0]; // we need this pointer to calculate real size of structure +}stored_data; + +typedef struct{ + stored_data all_stored; char struct_end[0] __attribute__ ((aligned(FLASH_BLOCK_SIZE))); // this pointer provides size of structure multiple of page size } flash_data; -extern const flash_data Stored_Data; +extern stored_data Stored_Data; #define ADC_multipliers Stored_Data._ADC_multipliers #define ADC_divisors Stored_Data._ADC_divisors void dump_flash_data(sendfun s); -uint32_t flash_store_U32(uint32_t addr, uint32_t *data); +uint8_t save_flashdata(); +void read_stored_data(); #endif // __FLASH_H__ diff --git a/with_opencm3/hardware_ini.c b/with_opencm3/hardware_ini.c index 8f2df8c..007591a 100644 --- a/with_opencm3/hardware_ini.c +++ b/with_opencm3/hardware_ini.c @@ -137,7 +137,8 @@ void GPIO_init(){ // Shutter control: input pull up gpio_set_mode(SHUTTER_EXT_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, SHUTTER_CAM_PIN | SHUTTER_MAN_PIN | SHUTTER_FBSW_PIN); - gpio_set(SHUTTER_EXT_PORT, SHUTTER_CAM_PIN | SHUTTER_MAN_PIN | SHUTTER_FBSW_PIN); // turn on pull up + //gpio_set(SHUTTER_EXT_PORT, SHUTTER_CAM_PIN | SHUTTER_MAN_PIN | SHUTTER_FBSW_PIN); // turn on pull up + GPIO_ODR(SHUTTER_EXT_PORT) |= SHUTTER_CAM_PIN | SHUTTER_MAN_PIN | SHUTTER_FBSW_PIN; // shutter status LED: opendrain gpio_set_mode(LED_SHUTTER_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, LED_SHUTTER_PIN); diff --git a/with_opencm3/hardware_ini.h b/with_opencm3/hardware_ini.h index 9d9c42a..ee242b4 100644 --- a/with_opencm3/hardware_ini.h +++ b/with_opencm3/hardware_ini.h @@ -97,6 +97,8 @@ void ADC_calibrate_and_start(); #define MOTOR_TIM1_PIN (GPIO6) #define MOTOR_TIM2_PORT (GPIOD) #define MOTOR_TIM2_PIN (GPIO15) +// don't even try to move motor if motors' voltage less than 9.5V +#define MOTORS_VOLTAGE_THRES (950) /* * One Wire interface @@ -128,14 +130,6 @@ void ADC_calibrate_and_start(); #define LED_SHUTTER_OPEN() do{gpio_clear(LED_SHUTTER_PORT, LED_SHUTTER_PIN);}while(0) #define LED_SHUTTER_CLOSE() do{gpio_set(LED_SHUTTER_PORT, LED_SHUTTER_PIN);}while(0) -/* -// We use timer 1 to process pauses with shutter -#define Shutter_tim_isr tim1_isr -#define SHUTTER_TIM TIM1 -//#define NVIC_SHUTTER_IRQ NVIC_TIM5_IRQ -#define NVIC_SHUTTER_IRQ NVIC_TIM1_UP_IRQ -#define RCC_SHUTTER_TIM RCC_TIM1 -*/ // Shutter pins: PC0 & PC2 are polarity & on/off pins; PC1 is feedback pin #define SHUTTER_PORT (GPIOC) #define SHUTTER_ON_PIN (GPIO2) @@ -145,9 +139,9 @@ void ADC_calibrate_and_start(); #define SHUTTER_VOLTAGE_THRES (2000) // minimum voltage that should be on capasitor if power source is on #define SHUTTER_UNDERVOLTAGE_THRES (700) -// delay in operations (open/close) in us (according to shutter's datasheet it's about 12ms) -#define SHUTTER_DELAY (12500) -// delay for error test +// delay in operations (open/close) in milliseconds (according to shutter's datasheet it's about 12ms -> make 15) +#define SHUTTER_DELAY (15) +// delay for error test (in microseconds) #define SHUTTER_OP_DELAY (200) // ADC_value[8] is U36, ADC_value[9] is U10 diff --git a/with_opencm3/ircontroller.bin b/with_opencm3/ircontroller.bin index 9986659..c88648d 100755 Binary files a/with_opencm3/ircontroller.bin and b/with_opencm3/ircontroller.bin differ diff --git a/with_opencm3/main.c b/with_opencm3/main.c index 843cbfd..6bc00c1 100644 --- a/with_opencm3/main.c +++ b/with_opencm3/main.c @@ -137,18 +137,20 @@ void AD7794_init(){ int main(){ //int i; - uint32_t Old_timer = 0, lastTRDread = 0, lastTmon = 0; + uint32_t Shtr_blink_timer = 0, Old_timer = 0, lastTRDread = 0, lastTmon = 0; int oldusbdatalen = 0; //SPI_read_status SPI_stat; // RCC clocking: 8MHz oscillator -> 72MHz system rcc_clock_setup_in_hse_8mhz_out_72mhz(); - usb_disconnect(); // turn off USB while initializing all + + // turn off SWJ/JTAG + AFIO_MAPR = AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF; // GPIO GPIO_init(); - steppers_init(); + usb_disconnect(); // turn off USB while initializing all // init USART1 UART_init(USART1); @@ -173,9 +175,13 @@ int main(){ ADC_init(); ADC_calibrate_and_start(); + steppers_init(); + usb_connect(); // turn on USB shutter_init(); + read_stored_data(); // copy stored data into RAM + LED_STATUS_OK(); // All initialized - light up LED while(1){ usbd_poll(usbd_dev); @@ -200,9 +206,19 @@ int main(){ process_stepper_motors(); // check flags of motors' timers process_shutter(); // shutter state machine + if(Timer - Shtr_blink_timer > 500 || Timer < Shtr_blink_timer){ + Shtr_blink_timer = Timer; + // shutter LED will be blinking until init occurs + if(Shutter_State == SHUTTER_NOTREADY) + gpio_toggle(LED_SHUTTER_PORT, LED_SHUTTER_PIN); + } + if(Timer - Old_timer > 999){ // one-second cycle Old_timer += 1000; - // if(Shutter_State == SHUTTER_NOTREADY) shutter_init(); + // init shutter if error occurs + if(Shutter_State == SHUTTER_NOTREADY){ + shutter_init(); + } //OW_fill_ID(0); //gpio_toggle(GPIOC, GPIO12); // toggle LED //gpio_toggle(GPIO_BANK_SPI2_MOSI, GPIO_SPI2_MOSI); diff --git a/with_opencm3/powerhw.c b/with_opencm3/powerhw.c index 7029b1c..4f300d3 100644 --- a/with_opencm3/powerhw.c +++ b/with_opencm3/powerhw.c @@ -22,10 +22,9 @@ #include "main.h" // state of shutter - global variable to omit interface functions shutter_state Shutter_State = SHUTTER_NOTREADY; -uint16_t Shutter_delay = SHUTTER_DELAY; int8_t manual_pin_old_state = -1; int8_t camera_pin_old_state = -1; -uint8_t changed_manually = 0; // ==1 if shutter state was changed by manual switch +//uint8_t changed_manually = 0; // ==1 if shutter state was changed by manual switch // function to be runned from timer irq //void (*shutter_timer_fn)() = NULL; @@ -35,11 +34,12 @@ uint8_t changed_manually = 0; // ==1 if shutter state was changed by manual swit #define SCB_DEMCR *(volatile uint32_t *)0xE000EDFC /** - * Make background pause in 'us' microsecond, after which run function fn_ready + * Make blocking pause in 'us' microsecond, after which run function fn_ready * @param us - pause in microseconds * @param fn_ready - function to run at end of pause + * @param block - == 0 if calling is non-blocking, otherwice == 1 */ -void shutter_wait(uint32_t us, void(*fn_ready)()){ +void shutter_wait_block(uint32_t us, void(*fn_ready)()){ /* if(!fn_ready) return; //DBG("wait for previous .. "); @@ -55,12 +55,36 @@ void shutter_wait(uint32_t us, void(*fn_ready)()){ // wait for us*72 cycles SCB_DEMCR |= 0x01000000; DWT_CYCCNT = 0; - DWT_CONTROL|= 1; // enable the counter + DWT_CONTROL|= 1; // for (i = 0; i < us; i++) __asm__("nop"); while(DWT_CYCCNT < us); fn_ready(); } +/** + * Make nonblocking pause in 'ms' millisecond, after which we should run function fn_ready + * run it with us == 0 and/or fn_ready == 0 to check old pause + */ +void shutter_wait_nonblock(uint32_t ms, void(*fn_ready)()){ + static uint8_t waiting_for = 0; // == 1 if we are waiting for something + static uint32_t wait_till = 0; // time counter for waiting + static void(*fn_ready_saved)() = NULL; + if(ms == 0 || fn_ready == 0){ // check + if(waiting_for && Timer >= wait_till){ // it's time + waiting_for = 0; + if(fn_ready_saved){ + void(*f)() = fn_ready_saved; + fn_ready_saved = NULL; + f(); + } + } + }else{ + waiting_for = 1; + fn_ready_saved = fn_ready; + wait_till = Timer + ms; // "automatic" overload + } +} + // macro to open/close/set default state // open shutter is 0:0 -> when MCU power is off, shutter "automatically" opens #define shutter_close() do{gpio_clear(SHUTTER_PORT, SHUTTER_ON_PIN | SHUTTER_POLARITY_PIN);}while(0) @@ -83,7 +107,7 @@ void shutter_test(){ static shutter_state old_State = SHUTTER_NOTREADY; // test for undervoltage if(shutter_voltage() < SHUTTER_UNDERVOLTAGE_THRES){ - ERR("shutter undervoltage\n"); + // ERR("shutter undervoltage\n"); Shutter_State = SHUTTER_NOTREADY; shutter_off(); return; @@ -92,20 +116,20 @@ void shutter_test(){ old_State = Shutter_State; Shutter_State = SHUTTER_INITIALIZED; // test for wire breakage - DBG("breakage test\n"); + // DBG("breakage test\n"); shutter_hiZ(); // 1,1: breakage test - shutter_wait(SHUTTER_OP_DELAY, shutter_test); + shutter_wait_block(SHUTTER_OP_DELAY, shutter_test); }else{ // check breakage if(shutter_error()){ // ERR==0 -> wire breakage - ERR("shutter wire breakage\n"); + // ERR("shutter wire breakage\n"); Shutter_State = SHUTTER_NOTREADY; }else{ if(old_State == SHUTTER_NOTREADY){ Shutter_State = SHUTTER_CLOSING; // close shutter on power on - DBG("ready!\n"); + // DBG("ready!\n"); }else{ Shutter_State = old_State; - DBG("no errors\n"); + // DBG("no errors\n"); } } shutter_off(); @@ -131,8 +155,10 @@ void shutter_ready(){ LED_SHUTTER_CLOSE(); // turn off shutter status LED else{ ERR("shutter is still opened\n"); - if(!changed_manually) Shutter_State = SHUTTER_NOTREADY; + //if(!changed_manually) + Shutter_State = SHUTTER_NOTREADY; } + break; case SHUTTER_OPENED: if(shutter_error()){ ERR("shutter overtemperature or undervoltage\n"); @@ -142,7 +168,8 @@ void shutter_ready(){ LED_SHUTTER_OPEN(); // turn on LED else{ ERR("shutter is still closed\n"); - if(!changed_manually) Shutter_State = SHUTTER_NOTREADY; + //if(!changed_manually) + Shutter_State = SHUTTER_NOTREADY; } } break; @@ -163,15 +190,15 @@ void shutter_ready(){ ERR("wrong shutter state\n"); print_shutter_state(lastsendfun); } - changed_manually = 0; + //changed_manually = 0; shutter_off(); if(Shutter_State == SHUTTER_NOTREADY) return; if(test_err){ //DBG("now test for err\n"); - shutter_wait(SHUTTER_OP_DELAY, shutter_ready); // test for overtemp or undervoltage + shutter_wait_nonblock(SHUTTER_DELAY, shutter_ready); // test for overtemp or undervoltage }else{ // wait a lot of time to prevent false detections - shutter_wait(SHUTTER_DELAY, shutter_test); + shutter_wait_nonblock(SHUTTER_DELAY, shutter_test); } } @@ -208,10 +235,14 @@ shutter_state shutter_init(){ // feedback: floating input gpio_set_mode(SHUTTER_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, SHUTTER_FB_PIN); + // Shutter control: input pull up +// gpio_set_mode(SHUTTER_EXT_PORT, GPIO_MODE_INPUT, +// GPIO_CNF_INPUT_FLOAT, SHUTTER_CAM_PIN | SHUTTER_MAN_PIN | SHUTTER_FBSW_PIN); +// gpio_set(SHUTTER_EXT_PORT, SHUTTER_CAM_PIN | SHUTTER_MAN_PIN | SHUTTER_FBSW_PIN); // turn on pull up //DBG("shutter fb ready\n"); shutter_off(); //shutter_timer_fn = NULL; - shutter_wait(SHUTTER_OP_DELAY, shutter_test); + shutter_wait_block(SHUTTER_OP_DELAY, shutter_test); return SHUTTER_INITIALIZED; // we return this state in spite of the shutter isn't really initialized yet } @@ -221,6 +252,9 @@ shutter_state shutter_init(){ */ void process_shutter(){ uint8_t man_pin_state, cam_pin_state, ext_open = 0, ext_close = 0; + + shutter_wait_nonblock(0, NULL); // check for holded over functions + if(Shutter_State == SHUTTER_NOTREADY) return; // test state of external control pins @@ -240,7 +274,7 @@ void process_shutter(){ manual_pin_old_state = man_pin_state; }else if(manual_pin_old_state != man_pin_state){ // user changed switch state -> open/close manual_pin_old_state = man_pin_state; - changed_manually = 1; + //changed_manually = 1; if(man_pin_state){ // close ext_close = 1; }else{ // open @@ -252,13 +286,13 @@ void process_shutter(){ if(ext_open){ // external signal for opening shutter if(Shutter_State != SHUTTER_OPENED && Shutter_State != SHUTTER_PROC_OPENING) Shutter_State = SHUTTER_OPENING; - else - changed_manually = 0; + //else + // changed_manually = 0; }else if(ext_close){ // close shutter if(Shutter_State != SHUTTER_CLOSED && Shutter_State != SHUTTER_PROC_CLOSING) Shutter_State = SHUTTER_CLOSING; - else - changed_manually = 0; + //else + // changed_manually = 0; } if(Shutter_State != SHUTTER_OPENING && Shutter_State != SHUTTER_CLOSING) @@ -288,7 +322,7 @@ void process_shutter(){ default: return; } - shutter_wait(Shutter_delay, shutter_ready); + shutter_wait_nonblock(SHUTTER_DELAY, shutter_ready); } /* @@ -350,6 +384,15 @@ void print_shutter_state(sendfun s){ } if(mode == BYTE_MODE) P(")\n", s); else if(mode == LINE_MODE) P(") ]\n", s); +#ifdef EBUG + if(mode == BYTE_MODE){ + P("MAN: ",s); + if(gpio_get(SHUTTER_EXT_PORT, SHUTTER_MAN_PIN)) P("not ",s); + P("pressed, EXT: ",s); + if(gpio_get(SHUTTER_EXT_PORT, SHUTTER_CAM_PIN)) P("not ",s); + P("pressed\n", s); + } +#endif } /** diff --git a/with_opencm3/powerhw.h b/with_opencm3/powerhw.h index 1716ae2..670e569 100644 --- a/with_opencm3/powerhw.h +++ b/with_opencm3/powerhw.h @@ -39,7 +39,6 @@ typedef enum{ } shutter_state; extern shutter_state Shutter_State; -extern uint16_t Shutter_delay; shutter_state shutter_init(); void process_shutter(); diff --git a/with_opencm3/stepper_motors.c b/with_opencm3/stepper_motors.c index faf7785..7a46731 100644 --- a/with_opencm3/stepper_motors.c +++ b/with_opencm3/stepper_motors.c @@ -24,29 +24,37 @@ // TODO: function "move motor to given position" static uint8_t timers_activated[2] = {0, 0}; // flag of activated timers -uint16_t Motor_period[2] = {1300, 1300}; // one step per 1.3ms -uint32_t Turrets_pause = 2 * TURRETS_PAUSE_US / 1300; // pause in half-steps -volatile uint8_t timer_flag[2] = {0,0}; +static uint16_t Motor_period[2] = {3000, 2000}; +static uint32_t Turrets_pause = 2 * TURRETS_PAUSE_US / 3000; // pause in half-steps +static volatile uint8_t timer_flag[2] = {0,0}; // amount of steps for each motor -volatile uint32_t Motor_steps[5] = {0, 0, 0, 0, 0}; +static volatile uint32_t Motor_steps[5] = {0, 0, 0, 0, 0}; // absolute value of current position, usefull for stages -volatile int32_t Motor_abs_steps[5] = {0, 0, 0, 0, 0}; +static volatile int32_t Motor_abs_steps[5] = {0, 0, 0, 0, 0}; +// increments that will be added each step to Motor_abs_steps (+1/-1) +static int8_t Motor_step_increment[5] = {1,1,1,1,1}; // flag of active motor -volatile uint8_t Motor_active[5] = {0, 0, 0, 0, 0}; +static volatile uint8_t Motor_active[5] = {0, 0, 0, 0, 0}; /* * Wait flags: if non-zero, flag just decremented * (we need it to wait a little on turrets' fixed positions to omit Halls' histeresis) */ -uint8_t waits[5] = {0,0,0,0,0}; +static uint8_t waits[5] = {0,0,0,0,0}; +// acceleration: if non-zero we will omit N steps after each step & decrement accell value +static uint8_t accel[5] = {0,0,0,0,0}; // Halls & end-switches values on previous step -uint8_t lastpos[5] = {0,0,0,0,0}; +static uint8_t lastpos[5] = {0,0,0,0,0}; // number of position to move turret or stage, zero to move only for N given steps uint8_t move2pos[5] = {0,0,0,0,0}; // number of positions passed for given -uint8_t positions_pass[3] = {0,0,0}; +static uint8_t positions_pass[3] = {0,0,0}; // maximum amount of positions passed to reach given #define MAX_POSITIONS_PASS (8) +// multipliers for linear acceleration (in reverce order) +static const uint8_t accel_mults[16] = {1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 8, 10, 16}; + + /** * Setup stepper motors' timer Tim * N == 0 for TIM3, == 1 for TIM4 @@ -105,9 +113,10 @@ void steppers_init(){ GPIO_CNF_OUTPUT_PUSHPULL, MOTOR_TIM2_PIN); // EN pins // WARNING! EN pins would be shortened to GND in case of overcurrent/overheating - // so, they should be pull-up inputs in active mode & pull-down inputs in inactive mode!!! + // so, when active they should be opendrain outputs with 100k external resistor to +5V or pullup inputs!!! + // inactive: opendrain output gpio_set_mode(MOTOR_EN_PORT, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_INPUT_PULL_UPDOWN, MOTOR_EN_MASK); + GPIO_CNF_OUTPUT_OPENDRAIN, MOTOR_EN_MASK); gpio_clear(MOTOR_EN_PORT, MOTOR_EN_MASK); // DIR pins gpio_set_mode(MOTOR_DIR_PORT, GPIO_MODE_OUTPUT_2_MHZ, @@ -130,10 +139,10 @@ uint8_t test_stages_endpos(uint8_t num, uint8_t curpos){ const uint8_t stage_plus[2] = {STAGE_CHECK(3, PLUS), STAGE_CHECK(4, PLUS)}; const uint8_t stage_minus[2] = {STAGE_CHECK(3, MINUS), STAGE_CHECK(4, MINUS)}; uint8_t negative_dir = 0; - num -= 3; // convern num to index in arrays - if((uint16_t)(GPIO_IDR(MOTOR_DIR_PORT) & MOTOR_DIR_PIN(num))){ // negative direction + if((uint16_t)(GPIO_ODR(MOTOR_DIR_PORT) & MOTOR_DIR_PIN(num))){ // negative direction negative_dir = 1; } + num -= 3; // convern num to index in arrays if(stage_plus[num] == curpos){ // we are on "+" end-switch if(!negative_dir){ // and wanna move to "+" ERR("End-switch +\n"); @@ -180,6 +189,7 @@ uint8_t check_ep(uint8_t num){ return 0; } + /** * Move motor Motor_number to User_value steps * return 0 if motor is still moving @@ -192,6 +202,16 @@ uint8_t move_motor(uint8_t num, int32_t steps){ ERR("moving\n"); return 0; } + int voltage = power_voltage(); + if(voltage < MOTORS_VOLTAGE_THRES){ + ERR("undervoltage!\n"); + if(mode == LINE_MODE){ + P("[ " STR_MOTORS_VOLTAGE " ", lastsendfun); + print_int(voltage, lastsendfun); + P(" ]\n", lastsendfun); + } + return 0; + } #ifdef EBUG if(mode == BYTE_MODE){ P("move ", lastsendfun); @@ -201,11 +221,12 @@ uint8_t move_motor(uint8_t num, int32_t steps){ lastsendfun('\n'); } #endif - Motor_abs_steps[num] += steps; // fix absolute position if(steps < 0){ negative_dir = 1; + Motor_step_increment[num] = -1; steps = -steps; - } + }else + Motor_step_increment[num] = 1; curpos = check_ep(num); lastpos[num] = curpos; if(negative_dir){ @@ -220,10 +241,21 @@ uint8_t move_motor(uint8_t num, int32_t steps){ // set all flags and variables Motor_steps[num] = steps; // we run in full-step mode! waits[num] = 0; + accel[num] = START_MOTORS_ACCEL_IDX_4; Motor_active[num] = 1; if(num < 3) // this is turret -> reset counter of passed positions positions_pass[num] = 0; + // pullup input when active + gpio_set_mode(MOTOR_EN_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, MOTOR_EN_PIN(num)); gpio_set(MOTOR_EN_PORT, MOTOR_EN_PIN(num)); +/* + P("set: ", lastsendfun); + print_int(GPIO_ODR(MOTOR_EN_PORT) & MOTOR_EN_MASK, lastsendfun); + P(", get: ", lastsendfun); + print_int(GPIO_IDR(MOTOR_EN_PORT) & MOTOR_EN_MASK, lastsendfun); + lastsendfun('\n'); +*/ return 1; } @@ -232,10 +264,17 @@ void stop_motor(uint8_t num){ const uint8_t stage_minus[2] = {STAGE_CHECK(3, MINUS), STAGE_CHECK(4, MINUS)}; //if(!) return; MSG("stop motor ", "[ " STR_STOP_ALL_MOTORS " "); - if(mode != BINARY_MODE) lastsendfun('0' + num); + if(mode != BINARY_MODE){ + lastsendfun('0' + num); + lastsendfun(' '); + } + // this function could be called simply to check motors' position + // so, we should check wether motor is active before changing EN state if(Motor_active[num]){ if(!gpio_get(MOTOR_EN_PORT, MOTOR_EN_PIN(num)) && mode == LINE_MODE) - P(" HEAT ", lastsendfun); + P("HEAT ", lastsendfun); + gpio_set_mode(MOTOR_EN_PORT, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, MOTOR_EN_PIN(num)); gpio_clear(MOTOR_EN_PORT, MOTOR_EN_PIN(num)); Motor_active[num] = 0; } @@ -245,24 +284,16 @@ void stop_motor(uint8_t num){ move2pos[num] = 0; // reset target position value if(curpos == 1){ Motor_abs_steps[num] = 0; - goto retn; }else{ if(curpos == 0) // a turret is out of fixed position - MSG(" stop out of position", "ERR "); + MSG("stop out of position", "ERR "); } }else{ // linear stage if(curpos == stage_minus[num-3]){ Motor_abs_steps[num] = 0; - goto retn; } } - int32_t sign = 1; - if(GPIO_IDR(MOTOR_DIR_PORT) & MOTOR_DIR_PIN(num)){ // negative direction - sign = -1; - } - Motor_abs_steps[num] -= Motor_steps[num] * sign; Motor_steps[num] = 0; -retn: BYTE_MSG(" absolute steps: "); print_int(Motor_abs_steps[num], lastsendfun); if(mode == LINE_MODE) P(" ]", lastsendfun); @@ -287,10 +318,18 @@ void process_stepper_motors(){ const uint32_t pins[] = {MOTOR_TIM1_PIN, MOTOR_TIM2_PIN}; const uint8_t startno[] = {0, 3}; const uint8_t stopno[] = {3, 5}; + //static uint8_t showcurpos[5] = {0,0,0,0,0}; uint8_t curpos; + const uint32_t Tim[2] = {TIM3, TIM4}; for(j = 0; j < 2; j++){ + // new period of motors' timer -- maximum value for all periods in group + uint16_t new_period = 0; if(timer_flag[j]){ timer_flag[j] = 0; + uint8_t is_active = 0; + for(i = startno[j]; i < stopno[j]; i++) + if(Motor_active[i]) is_active = 1; + if(!is_active) continue; // don't generate clock pulses when there's no moving motors gpio_toggle(ports[j], pins[j]); // change clock state if(!gpio_get(ports[j], pins[j])){ // negative pulse - omit this half-step continue; @@ -303,16 +342,20 @@ void process_stepper_motors(){ //(what if there's some slipping or so on?) }else{ // we should move further if(waits[i]){ // waiting for position stabilisation + uint8_t got_new_position = 0; waits[i]--; if(waits[i]) continue; // there's more half-steps to skip + // tell user current position if we was stopped at fixed pos + if(lastpos[i] == 0 && curpos != 0){ + got_new_position = 1; + MSG("position of motor ", "[ " STR_ENDSW_STATE " "); + print_int(i, lastsendfun); + lastsendfun(' '); + print_int(curpos, lastsendfun); + if(mode == LINE_MODE) P(" ]", lastsendfun); + lastsendfun('\n'); + } lastpos[i] = curpos; - // tell user current position - MSG("position of motor ", "[ " STR_ENDSW_STATE " "); - print_int(i, lastsendfun); - lastsendfun(' '); - print_int(curpos, lastsendfun); - if(mode == LINE_MODE) P(" ]", lastsendfun); - lastsendfun('\n'); // turn on motor after pause gpio_set(MOTOR_EN_PORT, MOTOR_EN_PIN(i)); if(j == 1){ // this is a linear stage @@ -323,7 +366,7 @@ void process_stepper_motors(){ if(move2pos[i]){ // we should move to specific position if(curpos == move2pos[i]){ // we are on position stop_motor(i); - }else{ // add some steps to move to next position + }else if(got_new_position){ // add some steps to move to next position if(++positions_pass[i] > MAX_POSITIONS_PASS){ ERR("Can't reach given position"); stop_motor(i); @@ -341,17 +384,33 @@ void process_stepper_motors(){ } if(lastpos[i] != curpos){ // transition process if(lastpos[i] == 0){ // come towards position - waits[i] = Turrets_pause; - // turn off motor while a pause + if(j == 0){ // this is a turret: make pause & prepare acceleration for start + waits[i] = Turrets_pause; + accel[i] = START_MOTORS_ACCEL_IDX_4; + }else{ + waits[i] = 1; + } + // turn off motor while a pause (turret will be locked at fixed position by spring) + // for this short pause we can simply do a pulldown gpio_clear(MOTOR_EN_PORT, MOTOR_EN_PIN(i)); continue; } lastpos[i] = curpos; } Motor_steps[i]--; + // change value of current motor's position + Motor_abs_steps[i] += Motor_step_increment[i]; + if(accel[i]){ // we are starting + uint32_t NP = (uint32_t)Motor_period[j] * accel_mults[(accel[i]--)/4]; + if(NP > 0xffff) NP = 0xffff; + if(new_period < NP) new_period = (uint16_t)NP; + } } } } + if(new_period){ // we have to change motors' speed when accelerating + timer_set_period(Tim[j], new_period); + } } } } @@ -401,6 +460,33 @@ void set_motor_period(uint8_t num, uint16_t period){ else timer_set_period(Tim, period); } +void get_motors_position(){ + uint8_t i; + for(i = 0; i < 5; i++){ + MSG("position of ", "[ " STR_MOTOR_POSITION " "); + lastsendfun(i+'0'); + MSG(" is ", " "); + print_int(Motor_abs_steps[i], lastsendfun); + if(Motor_active[i]){ + lastsendfun(' '); + P("moving", lastsendfun); + } + if(mode == LINE_MODE) P(" ]", lastsendfun); + lastsendfun('\n'); + } +} + +/** + * displays periods of both generators + */ +void show_motors_period(sendfun s){ + P("[ " STR_SHOW_PERIOD " ", s); + print_int((int32_t)Motor_period[0],s); + s(' '); + print_int((int32_t)Motor_period[1],s); + P(" ]\n", s); +} + /* * Interrupts: just set flag */ diff --git a/with_opencm3/stepper_motors.h b/with_opencm3/stepper_motors.h index 135795d..c23e252 100644 --- a/with_opencm3/stepper_motors.h +++ b/with_opencm3/stepper_motors.h @@ -25,32 +25,45 @@ #include // default pause to make sure that turret is on position -#define TURRETS_PAUSE_US 30000 +#define TURRETS_PAUSE_US (50000) // max amount of steps to add to turret for moving to next position -#define TURRETS_NEXT_POS_STEPS 300 +#define TURRETS_NEXT_POS_STEPS (500) +// (index/4) in accel_mults[] for started acceleration +#define START_MOTORS_ACCEL_IDX_4 (63) #ifndef CONCAT #define CONCAT(A, B) A ## B #endif // check status of end-switches and Halls +/* // Motor 0 == turret 0, PD0..PD3 #define _CHECK_EP0 ((~GPIO_IDR(GPIOD)) & 0x0f) // Motor 1 == turret 1, PD4..PD6 #define _CHECK_EP1 (((~GPIO_IDR(GPIOD)) >> 4) & 0x07) // Motor 2 == turret 2, PD7, PB6, PB7 #define _CHECK_EP2 ((((~GPIO_IDR(GPIOD)) >> 7) & 0x01) | (((~GPIO_IDR(GPIOB))>> 6) & 0x03)) +*/ +// Motor 0 == turret 0, PD0..PD2 +#define _CHECK_EP0 ((~GPIO_IDR(GPIOD)) & 0x07) +// Motor 1 == turret 1, PD3..PD5 +#define _CHECK_EP1 (((~GPIO_IDR(GPIOD)) >> 3) & 0x07) +// Motor 2 == turret 2, PD6, PD7, PB6, PB7 +#define _CHECK_EP2 ((((~GPIO_IDR(GPIOD)) >> 6) & 0x03) | (((~GPIO_IDR(GPIOB))>> 4) & 0x0c)) // Motor 3 == long (VPHG, pupil stop) stage, PC7/PC8 (down/up) #define _CHECK_EP3 (((~GPIO_IDR(GPIOC)) >> 7) & 0x03) // Motor 4 == short (focus) stage, PC9/PA8 (down/up) -#define _CHECK_EP4 ((((~GPIO_IDR(GPIOC)) >> 9) & 0x01) | (((~GPIO_IDR(GPIOA)) >> 8) & 0x01)) +#define _CHECK_EP4 ((((~GPIO_IDR(GPIOC)) >> 9) & 0x01) | (((~GPIO_IDR(GPIOA)) >> 7) & 0x02)) + // this macro returns end-switches & Hall status: 0 - not active, 1 - active #define CHECK_EP(X) CONCAT(_CHECK_EP, X) // end-switches for motors 3,4 (stage 1 and stage 2): stop when direction positive/negative -#define EP3PLUS 2 -#define EP3MINUS 1 -#define EP4PLUS 2 -#define EP4MINUS 1 +// down is 1, up is 2 +// moving down is positive +#define EP3PLUS 1 +#define EP3MINUS 2 +#define EP4PLUS 1 +#define EP4MINUS 2 #define STAGE_CHECK(N, DIR) CONCAT(EP ## N, DIR) // setup ports: PA8, PB6, PB7, PC7..PC9, PD0..PD7 @@ -79,6 +92,8 @@ uint8_t move_motor(uint8_t num, int32_t steps); void stop_motor(uint8_t num); void set_motor_period(uint8_t num, uint16_t period); uint8_t check_ep(uint8_t num); +void get_motors_position(); +void show_motors_period(sendfun s); #endif // __STEPPER_MOTORS_H__ diff --git a/with_opencm3/user_proto.c b/with_opencm3/user_proto.c index 828a0f0..73d8cc2 100644 --- a/with_opencm3/user_proto.c +++ b/with_opencm3/user_proto.c @@ -41,11 +41,11 @@ enum{ UVAL_ENTERED, // value entered but not printed UVAL_BAD // entered bad value }; -uint8_t Uval_ready = UVAL_PRINTED; +static uint8_t Uval_ready = UVAL_PRINTED; int read_int(char *buf, int cnt); -intfun I = NULL; // function to process entered integer +static intfun I = NULL; // function to process entered integer #define READINT() do{i += read_int(&buf[i+1], len-i-1);}while(0) #define WRONG_COMMAND() do{if(mode == BYTE_MODE) command = '?';}while(0) @@ -110,18 +110,18 @@ int div_mul = 0; // 0 - multip., !0 - div. * change dividers/multipliers * work only in BYTE_MODE */ -uint8_t ch_divmul(int32_t v, sendfun s){ +uint8_t ch_divmul(int32_t v, _U_ sendfun s){ uint32_t val = (uint32_t) v; if(adc_channel == -1) return 0; if(div_mul){ // != 0 - divisors - flash_store_U32((uint32_t)&ADC_divisors[adc_channel], &val); + ADC_divisors[adc_channel] = val; }else{ // == 0 - mul - flash_store_U32((uint32_t)&ADC_multipliers[adc_channel], &val); + ADC_multipliers[adc_channel] = val; } adc_channel = -1; - P("stored\n", s); return 1; } + /** * Change divisor (work only in BYTE_MODE) * @param v - user value (sensor number) @@ -144,8 +144,9 @@ uint8_t try_ch_divmul(int32_t v, sendfun s){ */ uint8_t endswitchstate(int32_t v, sendfun s){ int32_t i; - if(v < 0 || v > 4){ - if(mode == BYTE_MODE) P("Wrong motor number\n", s); + if(v < 0 || v > 4){ // show all end-switches + for(i = 0; i < 5; i++) + endswitchstate(i, s); return 0; } i = check_ep(v); @@ -163,6 +164,11 @@ uint8_t endswitchstate(int32_t v, sendfun s){ if(mode == LINE_MODE) P(" ]\n", s); else s('\n'); } +/* +uint32_t h = (GPIO_IDR(GPIOD) & 0xff) | ((GPIO_IDR(GPIOB)<<2) & 0x300) | + ((GPIO_IDR(GPIOC)<<3) & 0x1C00) | ((GPIO_IDR(GPIOA)&0x100)<<5); +print_hex((uint8_t*)&h, 4, lastsendfun); +*/ return 0; } @@ -170,28 +176,32 @@ uint8_t endswitchstate(int32_t v, sendfun s){ * moves turret 'active_motor' to position v */ uint8_t move_turret(int32_t v, sendfun s){ - const int32_t maxpos[3] = {8, 6, 6}; // maximum position number for given turret + const int32_t maxpos[3] = {6, 6, 8}; // maximum position number for given turret int32_t sign = 1; if(active_motor > 2){ if(mode == BYTE_MODE) P("Wrong turret number\n", s); return 0; } int32_t m = maxpos[active_motor]; - if(v > m){ + if(v > m || v < 1){ if(mode == BYTE_MODE){ P("Wrong position, shoud be not more than ", s); print_int(m, s); } return 0; } + uint8_t curpos = check_ep(active_motor); + if(curpos == v){ // we are in that position + endswitchstate(active_motor, s); + return 1; + } move2pos[active_motor] = v; // check the nearest direction - uint8_t curpos = check_ep(active_motor); if(curpos){ // we are not between positions - if((v + m - curpos) > m/2) // rotation in positive direction will take more steps than in negative + if(((v + m - curpos) % m) > m/2) // rotation in positive direction will take more steps than in negative sign = -1; // move CCV } - return move_motor(active_motor, TURRETS_NEXT_POS_STEPS * sign); + return move_motor(active_motor, sign * TURRETS_NEXT_POS_STEPS); } /** @@ -207,7 +217,7 @@ void help(sendfun s){ pr("D\tturn AD7794 to double conversion mode"); pr(STR_ENDSW_STATE "\tshow end-switches state for given motor"); pr("F\tdump flash data"); - //pr("G"); + pr(STR_SHOW_PERIOD "\tget motors' speed"); pr("H\tshow this help"); pr("I\tturn off AD7794 init flag"); pr("J\tmove slits (0) wheel to Nth position"); @@ -226,13 +236,13 @@ void help(sendfun s){ //pr("W\t(reserved)"); pr("X\tset timer period for linear stages"); //pr("Y"); - //pr("Z"); + pr("Z\tShow motors' positions"); //pr("a"); //pr("b"); pr("c\tclose shutter"); pr("d\tchange value of ADC divisor No N"); //pr("e"); - //pr("f"); + pr("f\tsave current values of ADC mult/div to flash"); pr("g\tchange AD7794 gain"); pr(STR_SHTR_VOLTAGE "\tshow shutter voltage"); pr(STR_EXTADC_INIT "\tinit AD7794"); @@ -283,31 +293,24 @@ int parce_incoming_buf(char *buf, int len, sendfun s){ } }else if(mode == LINE_MODE){ // text mode: check for "]\n" presence uint8_t bad_cmd = 1; -s(buf[0]); -P(" check buffer in line mode: ", s); if(buf[0] == '['){ for(j = 1; j < len; j++){ -s(buf[j]); if(buf[j] != '\n') continue; // search end of line else{ if(buf[j-1] == ']'){ -P("OK, good!\n", s); bad_cmd = 0; len = j; buf[j] = 0; // truncate buffer to only one command break; } else{ -P("broken command!\n",s); return 0; // end of line without closing bracket } } }} else{ -P("wrong first\n",s ); return 0; } if(bad_cmd){ -P("not full\n",s); return len; // not enough data in buffer } } @@ -364,6 +367,16 @@ P("not full\n",s); I = endswitchstate; READINT(); break; + case 'f': // store flash data + if(mode != BYTE_MODE) return 0; + uint8_t f_flag = save_flashdata();// == 0 if all OK, or return error flag + if(f_flag){ + P("error! can't store data, errno: ", s); + print_int((int32_t) f_flag, s); + s('\n'); + }else + P("data stored successfully\n", s); + break; case 'F': // dump flash data (only in byte mode) if(mode != BYTE_MODE) return 0; dump_flash_data(s); @@ -373,6 +386,10 @@ P("not full\n",s); I = set_ADC_gain; READINT(); break; + case CMD_SHOW_PERIOD: // [G] get motors' speed + show_motors_period(s); + do_echo = 0; + break; case CMD_SHTR_VOLTAGE: // [h] show sHutter voltage * 100 if(mode == LINE_MODE) P("[ " STR_SHTR_VOLTAGE " ", s); print_int(shutter_voltage(), s); @@ -414,6 +431,7 @@ P("not full\n",s); print_int(power_voltage(), s); if(mode == LINE_MODE) P(" ]", s); newline(s); + do_echo = 0; break; case 'P': // (only for byte mode) if(mode != BYTE_MODE) return 0; @@ -472,6 +490,25 @@ P("not full\n",s); I = set_timr; READINT(); break; + case CMD_MOTOR_POSITION: // [Z]: show positions of all motors + get_motors_position(); + do_echo = 0; + break; +/* + case '_': + P("set: ", s); + print_int(GPIO_ODR(MOTOR_EN_PORT) & MOTOR_EN_MASK, s); + P(", get: ", s); + print_int(gpio_get(MOTOR_EN_PORT, MOTOR_EN_MASK), s); + s('\n'); + break; + case '(': + gpio_set(MOTOR_EN_PORT, MOTOR_EN_MASK); + break; + case ')': + gpio_clear(MOTOR_EN_PORT, MOTOR_EN_MASK); + break; +*/ case '\n': // show newline, space and tab as is case '\r': case ' ': diff --git a/with_opencm3/user_proto.h b/with_opencm3/user_proto.h index 8c19c96..11f7216 100644 --- a/with_opencm3/user_proto.h +++ b/with_opencm3/user_proto.h @@ -87,6 +87,8 @@ void print_hex(uint8_t *buff, uint8_t l, sendfun s); #define STR_STOP_ALL_MOTORS "B" #define CMD_ENDSW_STATE 'E' #define STR_ENDSW_STATE "E" +#define CMD_SHOW_PERIOD 'G' +#define STR_SHOW_PERIOD "G" #define CMD_SHTR_VOLTAGE 'h' #define STR_SHTR_VOLTAGE "h" #define CMD_EXTADC_INIT 'i' @@ -99,5 +101,7 @@ void print_hex(uint8_t *buff, uint8_t l, sendfun s); #define STR_SHTR_STATE "t" #define CMD_PRINT_TIME 'T' #define STR_PRINT_TIME "T" +#define CMD_MOTOR_POSITION 'Z' +#define STR_MOTOR_POSITION "Z" #endif // __USER_PROTO_H__