//Nataceni za Sluncem//(c) Jan Chroust 2013#include <main.h>#define PIN_SDA PIN_C4#define PIN_SCL PIN_C3#use i2c(master, sda=PIN_SDA, scl=PIN_SCL)#use rs232(baud=9600,parity=N,xmit=PIN_C7,rcv=PIN_C6,bits=8) //rcv TXD xmit RXD#include <math.h>#include <stdio.h>#include <stdlib.h>#include <input.c>#include <string.h>//Akcelerometr#define AK_W 0x38 //adresa akcelerometru zápis#define AK_R 0x39 //adresa akcelerometru ètení#define AK_XH 0x01 //osa X LSB#define AK_XL 0x02 //osa X MSB#define AK_YH 0x03 //osa Y LSB#define AK_YL 0x04 //osa Y MSB#define AK_ZH 0x05 //osa Z LSB#define AK_ZL 0x06 //osa Z MSB//Magnetometr#define MAG_W 0x3C //adresa akcelerometru zápis#define MAG_R 0x3D //adresa akcelerometru ètení#define MAG_XH 0x03 //osa X LSB#define MAG_XL 0x04 //osa X MSB#define MAG_ZH 0x05 //osa Y LSB#define MAG_ZL 0x06 //osa Y MSB#define MAG_YH 0x07 //osa Z LSB#define MAG_YL 0x08 //osa Z MSB//pripojeni motoru//AIN1 - pro vysku slunce#define AIN1 PIN_D0#define AIN2 PIN_D1//motor A -cerveny vodic na AOUT1//motor A -modry vodic na Aout2//AIN2 - pro azimut#define BIN1 PIN_D2#define BIN2 PIN_D3//motor B - cerveny vodic na BOUT2//motor B - modrý vodic na BOUT1signed int16 X, Y, Z,AX, AY, AZ; //promenne pro magnetometr a akcelerometrunsigned int16 azimutZAD, elevaceZAD;void setAK (void) //nastaveni akcelerometru{i2c_start();I2C_Write(AK_W);I2C_write(0x2A);I2C_write(0x01); //nastavi aktivni stavi2c_stop();}void setmag (void){i2c_start();I2C_Write(MAG_W);I2C_Write(0x00);I2C_Write(0x78);i2c_stop();Delay_ms(6);i2c_start();I2C_Write(MAG_W);I2C_Write(0x01);I2C_Write(0x00);i2c_stop();Delay_ms(6);i2c_start();I2C_Write(MAG_W);I2C_Write(0x02);I2C_Write(0x00);i2c_stop();Delay_ms(6);}int16 akR (int8 H, int8 L) //vycitani hodnot z akcelerometru{unsigned int8 XL=0,XH=0;signed int16 x;i2c_start();I2C_Write(AK_W);I2C_write(H);i2c_start();I2C_Write(AK_R);XH=i2c_read(0);i2c_stop();i2c_start();I2C_Write(AK_W);I2C_write(L);i2c_start();I2C_Write(AK_R);XL=i2c_read(0);i2c_stop();x = (((unsigned int16) XH << 8) + XL ); //prevod na 16bit hodnotux=x/4;return x;}int16 magR (int8 H, int8 L) //vycitani hodnot z magnetometru{unsigned int8 XL=0,XH=0;signed int16 x;i2c_start();I2C_Write(MAG_W);I2C_write(H);i2c_start();I2C_Write(MAG_R);XH=i2c_read(0);i2c_stop();i2c_start();I2C_Write(MAG_W);I2C_write(L);i2c_start();I2C_Write(MAG_R);XL=i2c_read(0);i2c_stop();x = (((unsigned int16) XH << 8) + XL );return x;}float elevace (void) //vypocet aktualni elevace panelu{//printf("Akcelerometr5: \r\n",);X= akR (AK_XH, AK_XL);Y= akR (AK_YH, AK_YL);Z= akR (AK_ZH, AK_ZL);AX=abs(X);AY=abs(Y)+250;AZ=abs(Z)+250;float a, b;a=(float)Y/Z;b=atan(a);b = (b/3.14)*180;b=abs(b);if(((AX>AY) || (AX>AZ))) //indikace prevraceni panelu{printf("Prevracený panel)\r\n", );}else{if(Z==0) //osetreni proti deleni 0{if(Y>0){b=180;}else{b=0;}}else{if(Z>0){if(Y>=0){b=90+b;}else{b=90-b;}}else{if(Y>=0){b=180-b;}else{b=270+b;}}}}// printf("uhel namereny %10.2f \r\n", b);if(b>355){b=0;}else{}return b;}float azimut (void) //vypocet aktualni vysky panelu{X= magR (MAG_XH, MAG_XL);Y= magR (MAG_YH, MAG_YL);Z= magR (MAG_ZH, MAG_ZL);AX=abs(X);AY=abs(Y);AZ=abs(Z);float a, b;a=(float)Y/X;b=atan(a);b = (b/3.14)*180;b=abs(b);if(X==0) //osetreni proti deleni 0{if(Y>0){b=90;}else{b=270;}}else{if(X>0){if(Y>=0){b=b;}else{b=360-b;}}else{if(Y>=0){b=180-b;}else{b=180+b;}}}if(b>355){b=0;}else{}return b;}void motorA (int8 H) //pro ovladani prvniho motoru - nastaveni vysky (elevace) solarniho panelu{switch(H){case 1: //reverzní chodoutput_low (AIN2);output_high (AIN1);break;case 2: //dopreduoutput_low (AIN1);output_high (AIN2);break;default:output_low (AIN2);output_low (AIN1);}}void motorB (int8 H) //pro ovladani druheho motoru - nastveni nazimutu solarniho panelu{switch(H){case 1: //reverzní chodoutput_low (BIN2);output_high (BIN1);break;case 2: //dopøeduoutput_low (BIN1);output_high (BIN2);break;default:output_low (BIN2);output_low (BIN1);}}void elevace_set (int16 H) //slouzi pro nastaveni nove vysky (elevace) panelu{//printf("Akcelerometr4: \r\n",);float a;int16 b,c;a=elevace();b= (int16) a;c=abs(H-b);while(c>2) //maximalni odchylka uhlu, aby nebylo potreba panelem hybat{while(H!=b) //probiha dokud se uhel panelu nerovna zadanemu na cele stupne{if(H>b){motorA(2);}else{motorA(1);}delay_ms (50); //cas sepnuti motorumotorA(3); //vypne motordelay_ms (50); //doma na ustaleni panelu pred merenima=elevace();b= (int16) a;c=abs(H-b);}}motorA(3); //vypne motorprintf("Podarene nastaveni vysky: %Ld\r\n", b);}void azimut_set (int16 H) //slouzi pro nastaveni azimutu panelu{float a;int16 b,c;a=azimut();b= (int16) a;c=abs(H-b);while(c>2) //maximalni odchylka uhlu, aby nebylo potreba panelem hybat{while(H!=b) //probiha dokud se uhel panelu nerovna zadanemu na cele stupne{if(H>b){motorB(2);}else{motorB(1);}delay_ms (50); //cas sepnuti motorumotorB(3); //vypne motordelay_ms (50); //doma na ustaleni panelu pred merenima=azimut();b= (int16) a;c=abs(H-b);}}motorA(3); //vypne motorprintf("Podarene nastaveni azimutu: %Ld\r\n", b);}void main(){setup_adc_ports(NO_ANALOGS|VSS_VDD);setup_adc(ADC_CLOCK_DIV_2);setup_spi(SPI_SS_DISABLED);setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);setup_timer_1(T1_DISABLED);setup_timer_2(T2_DISABLED,0,1);setup_ccp1(CCP_OFF);setup_comparator(NC_NC_NC_NC);motorA(3); //vyponuti motorumotorB(3);setAK(); //nastaveni akcelerometrusetmag(); //nastveni magnetometruprintf("System nataceni panelu \r\n",);while(TRUE){int i[10];int16 vysledek;int b=0;int c;//nacteni hodnoty elevace ze seriove linkydo {b++;i[b] = getchar();// printf("Zadana elevace %d \r\n", i[b]);} while (i[b] != ' ');b=b-1;switch(b){case 1:elevaceZAD=i[1]-48;break;case 2:elevaceZAD=(i[2]-48)+(i[1]-48)*10;break;case 3:elevaceZAD=(i[3]-48)+(i[2]-48)*10+((int16)i[1]-48)*100;break;default:}printf("Zadaná elevace %Ld \r\n", elevaceZAD);i=0;vysledek=0;b=0;c=0;//nacteni hodnoty azimutu ze seriove linkydo {b++;i[b] = getchar();//printf("Zadany azimut %d \r\n", i[b]);} while (i[b] != ' ');b=b-1;switch(b){case 1:azimutZAD=i[1]-48;break;case 2:azimutZAD=(i[2]-48)+(i[1]-48)*10;break;case 3:azimutZAD=(i[3]-48)+(i[2]-48)*10+((int16)i[1]-48)*100;break;default:}printf("Zadany azimut %Ld \r\n", azimutZAD);elevace_set (elevaceZAD); //pro nastveni nove elevace solarniho paneluazimut_set(azimutZAD); //pro nastaveni noveho azimutu solarniho paneludelay_ms (2000);}}