This program uses the "PSA" solar positioning algorithm calculating the sun position, based on longitude, latitude, and time zone. Then Mbed chip controls the two digital servos to rotate the solar panel to the correct azimuth and zenith angle.
Dependencies: 4DGL-uLCD-SE AX12 NetServices mbed spxml
Fork of AX12-HelloWorld by
main.cpp
- Committer:
- conantina
- Date:
- 2016-04-25
- Revision:
- 2:2a3493799f03
- Parent:
- 1:b12b06e2fc2d
File content as of revision 2:2a3493799f03:
/* This Mbed code is a demo code of a DIY dual-axis solar tracker Since the solar position is different from place to place, the variables: YourLongitude and YourLatitude needs to be changed based on user's location The PSA solar positioning algorithm use UTC. There may be a time difference. The variable time_difference should be calibrated as well. The calibration can be done by calculated the longitute difference between the user's loaction and Greenwich. 30 degree is 0.25 hours. The futher calibration can be done by compare the PSA results with the solar position GUI results, for example: http://www.esrl.noaa.gov/gmd/grad/solcalc/azel.html The real time needs to be set manually at the beginning of main function */ #include "mbed.h" #include "AX12.h" #include "Helios.h" #include "EthernetNetIf.h" #include "HTTPClient.h" #include "spdomparser.hpp" #include "spxmlnode.hpp" #include "spxmlhandle.hpp" #include <string> #include "uLCD_4DGL.h" uLCD_4DGL lcd(p9,p10,p11); // serial tx, serial rx, reset pin; EthernetNetIf eth; HTTPClient http; HTTPResult result; bool completed = false; void request_callback(HTTPResult r) { result = r; completed = true; } AX12 Hax12 (p13, p14, 1); AX12 Vax12 (p28, p27, 1); //uLCD_4DGL lcd(p28, p27, p29); Serial pc(USBTX,USBRX); Helios helios; /////////// TEMPORARY TEST VARIABLES ////////////////////// int TheYear = 2016; int TheMonth = 4; int TheDay = 9; double TheHour = 12; /* UTC TIME! */ double TheMinute = 0.00; double TheSeconds = 0.00; double YourLongitude = 84.39; // your longitude [e.g 151.857964]; double YourLatitude = 33.4; // your latitude [e.g -33.579265]; ////// LIVE VARIABLES SHOULD BE USED FROM A GPS ////////// //real_time variable struct tm *t; float time_difference = 6.1; //calibrated time difference of Atlanta //update the solar position and roate the panel accordingly with the time interval of update_period float update_period = 0.5*60; //10 minutes by default //HTTP variables int n = 0; string delimiter = "weather"; string delimiter2 = ","; string delimiter3 = ":"; string place; string weather; string condition; void get_sun_position(){ helios.calcSunPos(TheYear, TheMonth, TheDay, TheHour, TheMinute, TheSeconds, YourLongitude, YourLatitude); pc.printf("Sun Zenith Angle: %f\n",helios.dZenithAngle); // Degrees down from vertical pc.printf("Sun Azimuth Angle: %f\n",helios.dAzimuth); // Degrees from north pc.printf("Sun Elevation Angle: %f\n",helios.dElevation); // Degrees up from horizontal } //rotate the horizontal angle to get the proper azimuth angle void rotate_horizontal(float angle){ Hax12.SetGoal(angle); } //rotate the vertical angle to get the proper zenith angle, the zero of the servo points vertical void rotate_vertical(float angle){ Vax12.SetGoal(angle+60); } int main() { // setup time structure for Wed, 28 Oct 2016 3:12:00 struct tm mytime; mytime.tm_sec = 00; // 0-59 mytime.tm_min = 50; // 0-59 mytime.tm_hour = 16; // 0-23 mytime.tm_mday = 28; // 1-31 mytime.tm_mon = 3; // 0-11 mytime.tm_year = 116; // year since 1900 time_t seconds = mktime(&mytime); set_time(seconds); lcd.cls(); lcd.printf("Start\n"); lcd.printf("Setting up...\n"); EthernetErr ethErr = eth.setup(100000); if(ethErr) { lcd.printf("Error %d in setup.\n", ethErr); return -1; } lcd.printf("Setup OK\n"); HTTPStream stream; SP_XmlDomParser parser; char BigBuf[512 + 1] = {0}; stream.readNext((byte*)BigBuf, 512); //Point to buffer for the first read int i = 0; char buffer [512*5+1]; while(true){ HTTPResult r = http.get("http://openweathermap.org/data/2.1/find/city?lat=33.75&lon=-84.39&cnt=1&type=XML", &stream, request_callback); //Load a very large page, such as the hackaday RSS feed //http://openweathermap.org/data/2.1/find/city?lat=33.75&lon=-84.39&cnt=1&type=XML //http://wxdata.weather.com/wxdata/weather/local/USGA0028:1:US?cc=*&unit=m&dayf=1 //HTTP://hackaday.com/feed/ //http://openweathermap.org/data/2.1/find/city?lat=40.71&lon=-74.00&cnt=1&type=XML i = 0; while(!completed) { Net::poll(); //Polls the Networking stack if(stream.readable()) { i++; BigBuf[stream.readLen()] = 0; //Transform this buffer in a zero-terminated char* string parser.append( BigBuf, strlen(BigBuf)); // stream current buffer data to the XML parser if (i == 1){ sprintf(buffer,"%s",BigBuf); } else{ printf("%s",BigBuf); //Display it while loading } //Note: some servers do not like if you throttle them too much, so printf'ing during a request is generally bad practice stream.readNext((byte*)BigBuf, 512); //Buffer has been read, now we can put more data in it } } //lcd.printf("\n--------------\n"); n = sizeof(buffer); string ret(buffer, n); place = ret.substr(ret.find("name"),ret.length()); place = place.substr(place.find(delimiter3),place.find(delimiter2)-4); //lcd.printf("Location:%s\n", place); weather = ret.substr(ret.find(delimiter), ret.length()); weather.erase(0,weather.find(delimiter3)+1); condition = weather.substr(weather.find("main"),weather.length()); condition = condition.substr(condition.find(delimiter3),place.find(delimiter2)-2); //lcd.printf("weather condition%s\n",condition); while (true) { time_t local_time = time(NULL); lcd.cls(); lcd.printf("The Current Time is: %s\n", ctime(&local_time)); pc.printf("The Current Time is: %s\n", ctime(&local_time)); lcd.printf("\n--------------\n"); lcd.printf("Location:%s\n", place); lcd.printf("weather condition%s\n",condition); pc.printf("weather condition%s\n",condition); t = localtime(&local_time); TheYear = t->tm_year + 1900; TheMonth = t->tm_mon; //change the local time to UTC TIME according to longitude if(t->tm_hour - time_difference < 0){ TheDay = t->tm_mday -1; TheHour = t->tm_hour + 24 - time_difference; } else{ TheDay = t->tm_mday; TheHour = t->tm_hour - time_difference; } TheMinute = t->tm_min; TheSeconds = t->tm_sec; get_sun_position(); pc.printf("%d\n",condition.find("Clear")); if( helios.dZenithAngle<90 && (condition.find("Clear")!=-1)){ rotate_horizontal(helios.dAzimuth); rotate_vertical(helios.dZenithAngle); lcd.printf("Sun Zenith Angle: %f\n",helios.dZenithAngle); // Degrees down from vertical lcd.printf("Sun Azimuth Angle: %f\n",helios.dAzimuth); // Degrees from north }else{ lcd.printf("The solar tracker is not tracking the sun..."); } wait(update_period); if(t->tm_hour == 6) break; } } }