/********************************************* * Author: Elmar Benninghaus, Copyright: GPL * This program is the eltel program for board * elavr32 * Chip type : ATmega32/16 * Clock frequency :14,7456Mhz MHz A program for steering parallactical, and Alt-Azimuth-telescopes. *********************************************/ #include "prog.h" #include "../../inc/global.h" #include "../../inc/utils.c" #include "../../inc/lcd.c" #include "../../inc/serial.c" #include "../../inc/i2csig.c" #include "../../inc/pfc8583.c" #include "../../inc/key.c" #include "cfg.c" #include "int.c" #include "astro.c" #include "usr.c" #include "koor.c" const prog_char row_version[16] = "Version 0.82\0"; const prog_char row_name[16] = "*** ELTEL ***\0"; const prog_char row_polaris[8] = "POLARIS\0"; const prog_char row_mainmenu[29][12] = { "RUN SCOPE \0", "DATABASE KR\0", "MANUAL KR \0", "ORG SC=KR \0", "COR KR=SC \0", "Date \0", "Time \0", "Latitude \0", "Longitude \0", "Fact. HOR \0", "Fact. VER \0", "Fact. FR \0", "Frqstep hor\0", "Frqstep ver\0", "Frqstep fr \0", "Mount azalt\0", "Enc. HOR nr\0", "Enc. VER nr\0", "Mot. MS HOR\0", "Mot. MS VER\0", "Mot. MS FR \0", "Correct C \0", "Correct R \0", "Calc. HOR \0", "Calc. VER \0", "Pos. to 0 \0", "Update CFG \0", "LOAD CONFIG\0", "CHANGE VIEW\0" }; const prog_char row_menu2[2][12] = { "MAINMENU \0", "ORG SC=KR \0" }; volatile double FACTOR_ENC_HOR; volatile double FACTOR_ENC_VER; //POSITION: DRV-TARGET = calculated position from KOOR_AZ/ALT //initiates values for the interrupt where it have to move to. //( over 200 times per second for all three motors //- we need 150 timers per second for 1/10 arcsecond prec. ) //After this normally interrupt has a new target/az/alt/fr //calculated from current set ra/dec position KOOR.ra/KOOR.dec // //After this KOOR_AZ(RA), / KOOR_ALT(DEC) which are the current //set KOORDINATE is calculated as new actual targetposition, which //also is send to driver. void position_Scope( void ){ double ftmp1,ftmp2,ftmp3,ftmp; LAST = (double)il_last * (double)NORMSEC_0400_STPART; if( ISFLAGAZALT ){ cAzAlt(); //to 1/10 arcseconds * min microstepsize ftmp1 = KOOR_AZ * 36000.0 * cfg.FACTOR_HOR; ftmp2 = KOOR_ALT * 36000.0 * cfg.FACTOR_VER; //calculate fieldrotator ftmp3 = KOOR_AZ * 36000.0 * cfg.FACTOR_FR; } else { //@@??testen ftmp = REST( LAST - KOOR.ra + 24.0, 24.0 ); ftmp1 = ftmp * 540000.0 * cfg.FACTOR_HOR; // ( 15.0 * 36000.0 ) = 540000.0 ftmp2 = KOOR.dec * 36000.0 * cfg.FACTOR_VER; //calculate fieldrotator ftmp3 = ftmp * 540000.0 * cfg.FACTOR_FR; } SETFLAGSPISTEPON; mot_target((long)ftmp1,(long)ftmp2,(long)ftmp3); } //POSITION: DRV-TARGET = calculated position from KOOR_AZ/ALT //ORIGIN: DRV-CURRENT = the same //origin means, - the current position of //scope is correctly the position where scope //points to the current set koordinates. //set ra/dec position KOOR.ra/KOOR.dec. //So the hardware-position will be set to //this. //( positioning of scope to polaris f.exmpl. ) // //After this KOOR_AZ(RA), / KOOR_ALT(DEC) which are the current //set KOORDINATE is calculated as new actual targetposition, which //also is send to driver. //From this targetposition, the current position will be set, with //is also send to driver. // //So after this the current set KOORDIANTE (KOOR_AZ/KOOR_ALT) is //the target as also the current position, where position is get //from set KOORDINATE. void origin_Scope(void){ double ftmp1,ftmp2; position_Scope(); //for having all actual times, and position. ftmp1 = (double)calctarget_hor / cfg.FACTOR_HOR / FACTOR_ENC_HOR; ftmp2 = (double)calctarget_ver / cfg.FACTOR_VER / FACTOR_ENC_VER; mot_origin(calctarget_hor,calctarget_ver,calctarget_fr,(int)ftmp1,(int)ftmp2); mot_stop(); //now here target, and current should be the same. } //CORRECT: KOOR_AZ/ALT = DRV-CURRENT //POSITION: DRV-TARGET = calculated position from KOOR_AZ/ALT +/- correction //correct_Koor means, - we will use current //scope-position as new ra/dec position. //So we calculate the KOOR.ra/KOOR.dec from current //scope-position. //This should only be used if scope is correctly positioned //before, once a time, by using origin. //It is also used by manual - moving, with right,left,up, and down keys. // //Normally after this, the KOORDINATE will be //changed to the current position, which is normally received from //the driver. //For having an actual value, the KOORDINATE will be recalculated //new, and send as target to the driver. // //Normally after this current, and targetposition should be the same, //where value is get from current position +/- additions. void correct_Koor( int horadd, int veradd ){ double ftmp; mot_stop(); //we stop all //now drivers target is the same as its currentpos, //STEP_ON is cleared, so no steps will be done, //also pos_hor,pos_ver,pos_fr contains drivers currentpos. if( horadd ){ if( horadd > 0 ){ pos_hor = pos_hor + (long)horadd; if( pos_hor >= hor_360 ){ pos_hor = pos_hor - hor_360; } } else { pos_hor = pos_hor - horadd; if( pos_hor < 0 ){ pos_hor = pos_hor + hor_360; } } } if( veradd ){ if( veradd > 0 ){ pos_ver = pos_ver + (long)veradd; if( pos_ver >= ver_360 ){ pos_ver = pos_ver - ver_360; } } else { pos_ver = pos_ver - veradd; if( pos_ver < 0 ){ pos_ver = pos_ver + ver_360; } } } //now, we calculate koordinates from current position. if( ISFLAGAZALT ){ KOOR_AZ = (double)pos_hor / (double)36000.0 / cfg.FACTOR_HOR; KOOR_ALT = (double)pos_ver / (double)36000.0 / cfg.FACTOR_VER; LAST = (double)il_last * (double)NORMSEC_0400_STPART; cRaDec(); } else { ftmp = (double)pos_hor / (double)540000.0 / cfg.FACTOR_HOR; KOOR.ra = REST( LAST - ftmp + 24.0, 24.0 );//@@??testen KOOR.dec = (double)pos_ver / (double)36000.0 / cfg.FACTOR_VER; } position_Scope(); //current pos, recalculated as target, and start again } //CORRECTT: current/target raw = DRV-CURRENT //POSITION: DRV-TARGET = current/target raw +/- correction //this is normally used only by manual-moving. //it affects none of the koordinates. void correct_Target( int horadd, int veradd ){ mot_stop();//we stop all, for having a none-changed currentpos. //now drivers target is the same as its currentpos, //STEP_ON is cleared, so no steps will be done, //also pos_hor,pos_ver,pos_fr contains drivers currentpos. calctarget_hor = pos_hor; calctarget_ver = pos_ver; calctarget_fr = pos_fr; if( horadd ){ if( horadd > 0 ){ calctarget_hor = calctarget_hor + (long)horadd; if( calctarget_hor >= hor_360 ){ calctarget_hor = calctarget_hor - hor_360; } } else { calctarget_hor = calctarget_hor - horadd; if( calctarget_hor < 0 ){ calctarget_hor = calctarget_hor + hor_360; } } } if( veradd ){ if( veradd > 0 ){ calctarget_ver = calctarget_ver + (long)veradd; if( calctarget_ver >= ver_360 ){ calctarget_ver = calctarget_ver - ver_360; } } else { calctarget_ver = calctarget_ver - veradd; if( calctarget_ver < 0 ){ calctarget_ver = calctarget_ver + ver_360; } } } SETFLAGSPISTEPON; // and now let him run. mot_target(calctarget_hor,calctarget_ver,calctarget_fr); } volatile unsigned char status[5]; //this is called at programstart, //and whenever a scope-dependent //value is changed, also if latitude,longitude is changed, //or another config is loaded. void recalculate_Scope( void ){ float ftmp; CLRFLAGSPISTEPON;//no moving to target, if running anywhere. ftmp = 12960000.0 * cfg.FACTOR_HOR; hor_360 = (long)ftmp; ftmp = 12960000.0 * cfg.FACTOR_VER; ver_360 = (long)ftmp; ftmp = 12960000.0 * cfg.FACTOR_FR; fr_360 = (long)ftmp; FACTOR_ENC_HOR = 12960000.0 / (double)cfg.ENCODERVAL_HOR; FACTOR_ENC_VER = 12960000.0 / (double)cfg.ENCODERVAL_VER; status[0] = '-'; status[1] = '-'; status[2] = '-'; status[3] = 'C'; status[4] = 0; spi_config(); if( addr_hor != 0xff ){ status[0] = 'h'; } if( addr_ver != 0xff ){ status[0] = 'v'; } if( addr_fr != 0xff ){ status[0] = 'f'; } spi_start(); origin_Scope(); mot_stop(); } unsigned char cfgget_microstep(void){ unsigned char ret; ret = usr_choose_motms(1, 0); switch( cfg.MOTORMS_HOR ){ case 0: return(16); case 1: return(8); case 2: return(4); case 3: return(2); case 4: return(1); default:return(1); } return(1); } int main(void) { int menuptr; unsigned int viewctr; unsigned char key,view,curconfig; double ftmp; #ifdef SPEEDTEST int itmp; long ltmp; #endif /////////////////////////////////////////////////////// //// BOARD - FIRST - SIGNALSETUP - START ////////////// /////////////////////////////////////////////////////// // After startup all Ports set as input // with value 0 ( no pullups ). //PORT A Signals - LCD, Analog-Keyinput /* Port A0 is analog input for keys Port A1 is output ENABLE for LCD Port A2 is output RS for LCD Port A3 is output RD/-WR for LCD Port A4,A5,A6,A7 is 5 bit dataport to LCD Startup situation should be: PA0 input no pullup PA1 output low PA2 output low PA3 output low PA4,5,6,7 output high */ DDRA = 0xFE; //set io-pins on PortA Porta1, to Porta7 //as output, but leave Porta0 as it is. PORTA = 0; //all to 0 //???? SFIOR&=!(1< 60000 ){ viewctr = 0; LCDPos(0,12); LCDWrite((char *)&status); LCDPos(1,0); LCDWriteP((char *)&row_blank); LCDPos(1,0); LCDWrite((char *)KOOR.name); switch( view ){ //shows current set koodinates as RA/DEC case 0: printDegrees(2, KOOR.ra, 0, 1, NULL); printDegrees(3, KOOR.dec, 3, 0, NULL); break; //shows current set koordinates as AZ/ALT case 1: LAST = (double)il_last * (double)NORMSEC_0400_STPART; cAzAlt(); printDegrees(2, KOOR_AZ, 3, 0, NULL); printDegrees(3, KOOR_ALT, 3, 0, NULL); break; //shows the calculated value from encoders. case 2: ftmp = (double)epos_hor * cfg.FACTOR_HOR; printDegrees(2, ftmp, 2, 1, NULL); ftmp = (double)epos_ver * cfg.FACTOR_VER; printDegrees(3, ftmp, 2, 0, NULL); break; //print utc-date,time case 3: printDateTime(); break; //print the raw current positions case 4: printLong(2, pos_hor ); printLong(3, pos_ver); break; default:break; } } continue; } if( ( key = readkey()) != NOKEY ){ if( key == KEY_UP ){ correct_Target(0,cfg.CORRECT_C); continue; } if( key == KEY_LEFT ){ correct_Target( 0 - cfg.CORRECT_C ,0); continue; } if( key == KEY_RIGHT ){ correct_Target( cfg.CORRECT_C ,0); continue; } if( key == KEY_DOWN ){ correct_Target(0 , 0 - cfg.CORRECT_C ); continue; } if( key == KEY_MENU_LEFT ){ if( menuptr > 0 ){ menuptr--; } else { menuptr = 28; } LCDPos(0,0); LCDWriteP((char *)&row_mainmenu[menuptr]); continue; } if( key == KEY_MENU_RIGHT ){ menuptr++; if( menuptr > 28 ){ menuptr = 0; } LCDPos(0,0); LCDWriteP((char *)&row_mainmenu[menuptr]); continue; } if( key == KEY_STOP_MOT ){ mot_stop(); continue; } if( key == KEY_ACK_MENU ){ switch( menuptr ){ case 0: //switch to loop guiding/goto SETFLAGRUN; break; case 1: //database chooseDbKoor( 0, (struct RADECKOOR *)&KOOR ); break; case 2: //manual koor setusrRaDec((struct RADECKOOR *)&KOOR ); break; case 3: //origin, uses current set KOOR_AZ/ALT, and //sets DRV-current/target pos from this. origin_Scope(); break; case 4: //correction, uses DRV-current position, and //recalculates KOOR_AZ/ALT from this, and //sets DRV-target from this. correct_Koor(0,0); break; case 5: cbi( TIMSK, TOIE0);//disable timer0 overflow int if( setusrDate(1) ){ rtc_set_time(); } else { sbi( TIMSK, TOIE0);//enable timer0 overflow int } recalculate_Scope(); break; case 6: cbi( TIMSK, TOIE0);//disable timer0 overflow int if( setusrTime(1) ){ rtc_set_time(); } else { sbi( TIMSK, TOIE0);//enable timer0 overflow int } recalculate_Scope(); break; case 7: //set latitude cfg.LATITUDE = setusrDoubleDegree( 1,cfg.LATITUDE ); recalculate_Scope(); break; case 8: //set longitude cfg.LONGITUDE = setusrDoubleDegree( 1,cfg.LONGITUDE ); //for longitude we have to set also il_last cfg.LONGITUDE = ftmp; cCurrentStarTime(); ftmp = LAST / NORMSEC_0400_STPART; //cbi( TIMSK, TOIE0);//disable timer0 overflow int il_last = (long)ftmp; //sbi( TIMSK, TOIE0);//enable timer0 overflow int recalculate_Scope(); break; case 9: //set factor az cfg.FACTOR_HOR = setusrDoubleDegree( 1,cfg.FACTOR_HOR ); recalculate_Scope(); break; case 10: //set factor alt cfg.FACTOR_VER = setusrDoubleDegree( 1,cfg.FACTOR_VER ); recalculate_Scope(); break; case 11: cfg.FACTOR_FR = setusrDoubleDegree( 1,cfg.FACTOR_FR ); recalculate_Scope(); break; case 12: //set steplp-az cfg.FRQSTEP_HOR = (unsigned char)setusrInt( 1,(int)cfg.FRQSTEP_HOR ); break; case 13: //set steplp-alt cfg.FRQSTEP_VER = (unsigned char)setusrInt( 1,(int)cfg.FRQSTEP_VER ); break; case 14: //set steplp-fr cfg.FRQSTEP_FR = (unsigned char)setusrInt( 1,(int)cfg.FRQSTEP_FR ); break; case 15: //set mount az/alt if( setusrFlag( 1, ISFLAGAZALT )){ SETFLAGAZALT; } else { CLRFLAGAZALT; } recalculate_Scope(); break; case 16: //set encodervalue cfg.ENCODERVAL_HOR = setusrInt( 1,cfg.ENCODERVAL_HOR ); recalculate_Scope(); break; case 17: //set encodervalue cfg.ENCODERVAL_VER = setusrInt( 1,cfg.ENCODERVAL_VER ); recalculate_Scope(); break; case 18: //set ms motor hor //16 = 1/2 FS //8 = 1/4 FS //4 = 1/8 FS //2 = 1/16 FS //1 = 1/32 FS cfg.MOTORMS_HOR = cfgget_microstep(); break; case 19: //set ms motor ver cfg.MOTORMS_VER = cfgget_microstep(); break; case 20: //set ms motor fr cfg.MOTORMS_FR = cfgget_microstep(); break; case 21: //set correctvalue top-view cfg.CORRECT_C = setusrInt( 1,cfg.CORRECT_C ); break; case 22: //set correctvalue run-view cfg.CORRECT_R = setusrInt( 1,cfg.CORRECT_R ); break; case 23: //calc cfg.FACTOR_HOR from pos_hor for 360 Degrees cfg.FACTOR_HOR = (double)pos_hor / 12960000.0; break; case 24: //calc cfg.FACTOR_VER from pos_alz for 90 Degrees cfg.FACTOR_VER = (double)pos_ver / 3240000.0; break; case 25: //set drv-current, and target to 0 mot_origin(0,0,0,0,0); mot_stop(); calctarget_hor = 0; calctarget_ver = 0; calctarget_fr = 0; break; case 26: //update config storeCfg( curconfig ); break; case 27: //load config key = usr_choose_cfg(1,curconfig); if( key < 3 ){ curconfig = key; if( loadCfg( curconfig ) ){ ; } recalculate_Scope(); } break; case 28: //change view view = usr_choose_view(1,view); break; default:break; } menuptr = 0; LCDCls(); LCDWriteP((char *)&row_mainmenu[menuptr]); } key = 0; } //R - LAYER GUIDE/GOTO //Here the scope will run, which means //scope will allways try to run to position //KOOR.ra/KOOR.dec. //User can position the scope outside of //current KOOR.ra/DEC, which recalculates this. //Also user can origin corrected/current KOOR.ra/DEC as //current scope-position. if( ISFLAGRUN ){ //preparations for programloop status[3] = 'R'; LCDCls(); LCDWriteP((char *)&row_menu2[menuptr]); LCDPos(0,12); LCDWrite((char *)&status); printDegrees(2, KOOR.ra, 3, 0, NULL); printDegrees(3, KOOR.dec, 3, 0, NULL); #ifdef SPEEDTEST itmp = SECOND; while( SECOND == itmp ){ NOP; } ltmp = 0; itmp = SECOND; #endif while( ISFLAGRUN ){ //here is the loop for the functionality program position_Scope(); #ifdef SPEEDTEST ltmp++; if( itmp != SECOND ){ CLRFLAGRUN; mot_stop(); break; } #endif if( ( key = testkey()) != NOKEY ){ key = readkey(); switch(key){ case KEY_UP: //move upwards correct_Koor(0, cfg.CORRECT_R ); break; case KEY_LEFT: correct_Koor( 0 - cfg.CORRECT_R , 0); break; case KEY_RIGHT: //move to the right correct_Koor( cfg.CORRECT_R ,0); break; case KEY_DOWN: //move downwards correct_Koor(0, 0 - cfg.CORRECT_R ); break; case KEY_STOP_MOT: mot_stop(); break; case KEY_MENU_LEFT: if( menuptr > 0 ){ menuptr--; } else { menuptr = 1; } break; case KEY_MENU_RIGHT: menuptr++; if( menuptr > 1 ){ menuptr = 0; } break; case KEY_ACK_MENU: switch( menuptr ){ case 0: //stop running position_Scope(); mot_stop(); CLRFLAGRUN; break; case 1: //origin origin_Scope(); break; default:break; } menuptr = 0; break; default: break; }//end switch key LCDCls(); LCDWriteP((char *)&row_menu2[menuptr]); LCDPos(0,12); LCDWrite((char *)&status); printDegrees(2, KOOR.ra, 3, 0, NULL); printDegrees(3, KOOR.dec, 3, 0, NULL); }//end key != NOKEY }//end while(ISFLAGRUN) #ifdef SPEEDTEST LCDCls(); printLong( 0 , ltmp ); Delay1ms(2000); #endif menuptr = 0; LCDCls(); LCDWriteP((char *)&row_mainmenu[menuptr]); status[3] = 'C'; }//end if(ISFLAGRUN) }//end of mainloop }//end of main /////////////////////