Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed mbed-rtos AMC7812B EthernetInterface TextLCD
main.cpp
00001 /********************************************************************* 00002 * 00003 * Driver Heaters DCM 8 channel - v4 (improvements) 00004 * 00005 * Mauricio Martins Donatti 00006 * mauricio.donatti@lnls.br 00007 * 00008 * Electronic Support Group - GAE 00009 * Brazilian Synchrotron Light Laboratory (LNLS) 00010 * Brazilian Center for Research in Energy and Materials (CNPEM) 00011 * 00012 * Jan 2021 00013 * 00014 * References: 00015 * - AMC7812B datasheet: http://www.ti.com/lit/ds/symlink/amc7812b.pdf 00016 * - Modification inside ethernet library: https://os.mbed.com/questions/1602/How-to-set-the-TCPIP-stack-s-hostname-pr/ 00017 * - VERY IMPORTANT: https://os.mbed.com/questions/61544/threaded-TCP-server-with-multi-port-it-r/ 00018 * 00019 *******************************************************************/ 00020 00021 #define SUPPLY_24V 00022 //#define CAL 00023 00024 #include "mbed.h" 00025 #include "TextLCD.h" 00026 #include "EthernetInterface.h" 00027 #include "amc7812b.h" 00028 00029 #define ERROR_INTERFACE 00030 //#define DEBUG_INTERFACE 00031 00032 #include "definitions.h" 00033 #include "HTTP_SERVER.h" 00034 00035 #define VERSION "v4.1-2021-07\0" //Firmware Version 00036 #define DEVICE_NAME "DH-8CH-001\0" //Device Name - Ethernet default hostname 00037 00038 #define PORT 6767 //Socket Port (EPICS data) 00039 00040 //SPI constructor 00041 SPI spi(MOSI,MISO,SCLK); //mosi, miso, sclk 00042 00043 Serial pc(USBTX, USBRX, 115200); 00044 00045 //Digital Output constructors 00046 DigitalOut cs_u4(CS_U4); 00047 DigitalOut cs_u5(CS_U5); 00048 DigitalOut amc_reset(RST); 00049 DigitalOut dac_clr(DAC_CLR); 00050 DigitalOut cnvt_u5(CNVT_U5); 00051 DigitalOut cnvt_u4(CNVT_U4); 00052 00053 //Digital Input constructors 00054 DigitalIn al_u4(AL_U4); 00055 DigitalIn al_u5(AL_U5); 00056 00057 //Interrupt Input constructors 00058 InterruptIn dav_u4(DAV_U4); 00059 InterruptIn dav_u5(DAV_U5); 00060 00061 //Digital output indicators 00062 DigitalOut blink(LED4); //Heartbeat at LED4 00063 DigitalOut socket_led(LED2); //Socket Connection LED 00064 DigitalOut led_cfg(LED3); //Configuration LED - ON only in configuration mode (adjusting current limit) 00065 DigitalOut server_led(LED1); //HTTP Server LED 00066 DigitalOut phy_rst(P1_28); //Ethernet PHY reset 00067 DigitalOut eth_led1(p29); //Ethernet LED1 00068 DigitalOut eth_led2(p30); //Ethernet LED2 00069 00070 //LCD Construtor 00071 Serial display(LCD_TX, LCD_RX); //LCD module initialization 00072 00073 //Timer Tickers 00074 Ticker start_convertion; //Triggers ADC convertion 00075 Timer t; //read ms timer to display and heartbeat functions 00076 00077 //There is a configuration file that can be accessed through usb in order to adjust current limits 00078 LocalFileSystem local("local"); //Create the local filesystem under the name "local" 00079 00080 //Variable Initialization 00081 EthernetInterface eth; //ethernet interface 00082 TCPSocketServer server; //Socket 00083 TCPSocketConnection client; //Client 00084 00085 //Create the variables structure for 8 channels (index 0 to 7) 00086 channel CH[8]; 00087 00088 //Create two spi global buffers - tx and rx 00089 //LPC1768 SPI works in 12 bits. AMC7812B spi works in 24 bits. 00090 union spi_buf{ //the same buffer may be expressed in two bytes (uint8_t) or a 16bit word (uint16_t) 00091 uint8_t byte[2]; 00092 uint16_t data; 00093 }rx,tx; 00094 00095 FILE *cfg_file; //Config file variable 00096 FILE *html_file; //Html file variable 00097 00098 int tmp,i; //auxiliary integers 00099 int LCD_index=0; //LCD index (displayed channel changes from 1 to 8) 00100 char LCD_buffer[40]; //LCD char buffer 00101 char cfg=0; //variable to identify config mode (config mode = current limit adjust mode) 00102 float mult = 10; //multiplier used in config mode 00103 char flag_adj=0; //flag to indicate adjust/config mode 00104 //int r,c; //auxiliary integers to LCD row and column 00105 uint8_t flag_end_u4,flag_end_u5; //flags to indicate AD end of convertion 00106 uint8_t register_amc; //8 bit variable to store AMC register to read/write 00107 uint16_t reg_aux; //Aux 16 bit variable used in spi read/write functions 00108 00109 //global variables for socket message treatment 00110 int ch_msg_idx,n; 00111 char tmp_char; 00112 float ilimit_msg; 00113 00114 Thread main_thread,server_thread,socket_thread; //threads instances 00115 Thread display_thread; //display thread (v3) 00116 volatile uint8_t new_cfg; //new config to save to file 00117 uint8_t display_status; 00118 uint8_t server_init=0,socket_init=0; //sockets init flags 00119 00120 HttpServer httpsvr; //http server instance 00121 00122 char socket_buffer[200]; //socket receive buffer 00123 char send_buffer[100]; //socket send buffer 00124 00125 int receive_return; //receive return for socket loop thread 00126 00127 char dev_name[30]; //device name string 00128 00129 //Display Functions 00130 void error(void); //Turn Red Led - Error Status 00131 void normal(void); //Turn Green Led - Normal Status 00132 void disabled(void); //Turn (Red + Green) - Channel disabled 00133 void write_LCD(void); //Write to LCD Function 00134 void reset_config(void); //Reset config buttons status 00135 void clear_lcd(void); //Clear LCD Function 00136 void heart(void); //Toggle function to heartbeat 00137 00138 //AMC7812B ADC and DAC functions 00139 void fast_read_U5(void); //U5 SPI fast read (returns previous transfer result) 00140 void fast_read_U4(void); //U4 SPI fast read (returns previous transfer result) 00141 void read_U5(void); //U5 SPI simple read - Takes two times the fast read 00142 void read_U4(void); //U4 SPI simple read - Takes two times the fast read 00143 void write_U5(void); //U5 SPI write 00144 void write_U4(void); //U4 SPI write 00145 00146 void setup(void); //Initialization (display and variables) 00147 void amc_setup(void); //AMC7812B setup (U4 and U5) 00148 00149 //Config and Output functions 00150 void adj_ilimit(int channel,float value); //Adjust current limit 00151 void fail_out(int channel,int value); //Set/Reset failure output 00152 00153 //End of convertion interruptions 00154 void end_conv_u4(void); //U4 end of convertion function (interruption called) 00155 void end_conv_u5(void); //U5 end of convertion function (interruption called) 00156 00157 //ADC convertion Trigger Functions 00158 void trigger_conv(void); //Trigger convertion function (start U4 and U5 convertion) - Ticker called 00159 void trigger_u4(void); //Trigger U4 only (not used) 00160 void trigger_u5(void); //Trigger U5 only (not used) 00161 00162 extern "C" void mbed_reset(); //mbed reset function 00163 00164 void message_treatment(void); //socket data received treatment 00165 00166 //Sockets functions 00167 void socket_start(); //initiate socket instances 00168 void server_loop(void); //Server threaded loop - Port 80 00169 void socket_loop(void); //Socket threaded loop - Port 5757 00170 00171 //Thread loops 00172 void main_loop(void); //main thread (real-time priority) - deals with the AMC devices 00173 void display_loop(void); //display update thread - deals with buttons and LCD (uart) 00174 00175 volatile int save_cfg_time; 00176 00177 char html_page[HTML_MAX_SIZE]; 00178 int html_page_size; 00179 00180 //main function 00181 int main() { 00182 //heartbeat.attach(&heart,HEARTBEAT_DELAY); //attach heartbeat ticker 00183 00184 t.start(); 00185 // Reading webserver file 00186 wait_ms(10); //Wait powerup 00187 00188 html_file = fopen("/local/index.htm","r"); // Open "index.html" on the local file system for reading 00189 if(html_file==NULL){ //If file doesnt exist 00190 html_page_size = sprintf(html_page,"ERROR: File Not Found"); 00191 ERROR_PRINTF("index.htm file not found at local file system!"); 00192 fclose(html_file); //close html file 00193 } 00194 else 00195 { //File exists 00196 fseek(html_file, 0, SEEK_SET); 00197 html_page_size = 0; 00198 while (!feof(html_file)) 00199 html_page[html_page_size++]= getc(html_file); 00200 if(feof(html_file)) 00201 html_page_size--; 00202 fclose(html_file); //close html file 00203 } 00204 00205 amc_setup(); //Setup AMC7812B 00206 setup(); //Initialize LCD and variables 00207 00208 dav_u4.fall(&end_conv_u4); //attach the address of the U4 end of convertion function to the falling edge 00209 dav_u5.fall(&end_conv_u5); //attach the address of the U5 end of convertion function to the falling edge 00210 00211 start_convertion.attach(&trigger_conv,CONV_DELAY); //attach ticker to trigger convertions - USED ONLY IN DIRECT MODE 00212 //trigger_conv(); //Start convertion - USED ONLY IN AUTO MODE 00213 00214 if (0 == eth.init())//Use DHCP 00215 { 00216 eth.setName(dev_name); 00217 00218 } 00219 else { 00220 clear_lcd(); 00221 display.printf("HW ERROR: eth conn"); //HW ethernet error - probably PHY broken 00222 ERROR_PRINTF("Ethernet Connection Hardware Error!"); 00223 //Turn LED 1 Red and Green - ETH HW Error 00224 display.putc(0xFE); 00225 display.putc(0x5A); 00226 display.putc(0x01); 00227 display.putc(0x03); 00228 } 00229 main_thread.set_priority(osPriorityRealtime); //Start AMCs thread with high high high priority 00230 server_thread.set_priority(osPriorityNormal); //HTTP server thread normal priority 00231 socket_thread.set_priority(osPriorityNormal); //Socket server (EPICS) normal priority 00232 display_thread.set_priority(osPriorityNormal); //Socket server (EPICS) normal priority 00233 00234 display_thread.start(display_loop); //Start AMC loop 00235 main_thread.start(main_loop); //Start AMC loop 00236 00237 while(1) 00238 { 00239 if(new_cfg==1 && t.read_ms() - save_cfg_time >= SAVE_CFG_DELAY_MIN) //File must be saved by the main thread. new_cfg is a flag indicating new data mus be saved 00240 { 00241 cfg_file = fopen("/local/lim.cfg", "w"); 00242 //Open "lim.cfg" on the local file system for writing 00243 fprintf(cfg_file,"Channel Configuration - Current Limit and Enable\n"); //Write header 00244 fprintf(cfg_file,"%s\n",dev_name); 00245 for(tmp=0;tmp<8;tmp++) 00246 { 00247 fprintf(cfg_file,"%d %3.2f %d\n",tmp+1,CH[tmp].limit,CH[tmp].enable); //Write current limits to file 00248 } 00249 fclose(cfg_file); //close file 00250 new_cfg=0; //reset flag 00251 } 00252 if(eth.is_connected()) //if eth connected 00253 { 00254 eth_led2 = !eth_led2; //toggle led2 00255 eth_led1 = 1; //turn on led1 00256 if(server_init == 0) //initiate http server the first time 00257 { 00258 httpsvr.init(html_page,html_page_size); 00259 server_init = 1; //turn flag on - Server initiated 00260 server_thread.start(server_loop); //run thread - monitoring port 80 00261 } 00262 if(socket_init == 0) //initiate socket server (PORT 5757) - EPICS 00263 { 00264 socket_start(); 00265 socket_init = 1; //turn flag on 00266 socket_thread.start(socket_loop); //run thread - monitoring port 5757 00267 } 00268 } 00269 else //connect ethernet 00270 { 00271 if(eth_led1) //eth_led serves also as flag 00272 { 00273 eth.disconnect(); //disconnect interface 00274 eth_led1=0; //turn leds off 00275 eth_led2=0; 00276 //Turn Display LED red 00277 display.putc(0xFE); 00278 display.putc(0x5A); 00279 display.putc(0x01); 00280 display.putc(0x02); 00281 } 00282 if (0 == eth.connect()) //once connected, display IP and hostname on LCD 00283 { 00284 //Turn Display LED green 00285 display.putc(0xFE); 00286 display.putc(0x5A); 00287 display.putc(0x01); 00288 display.putc(0x01); 00289 } 00290 } 00291 } 00292 } 00293 00294 void display_loop(void) 00295 { 00296 int display_time,heart_time; 00297 char blink_led,byte_read; 00298 display_time = t.read_ms(); 00299 heart_time = t.read_ms(); 00300 blink_led = 0x01; 00301 while(1) 00302 { 00303 if(t.read_ms()- display_time >= DISPLAY_DELAY*1000) 00304 { 00305 display_time = t.read_ms(); 00306 display_status = 0; 00307 if(cfg == 0) 00308 { //If not in config mode 00309 LCD_index = (LCD_index+1)%8; //Update index 00310 write_LCD(); //call write_LCD() 00311 } 00312 } 00313 if(t.read_ms()- heart_time >= HEARTBEAT_DELAY*1000) 00314 { 00315 heart_time = t.read_ms(); 00316 heart(); 00317 display.putc(0xFE); 00318 display.putc(0x5A); 00319 display.putc(0x02); 00320 display.putc(blink_led); 00321 blink_led = blink_led ^ 0x01; 00322 } 00323 if(display.readable()) { 00324 byte_read = display.getc(); 00325 if(byte_read=='B')//UP SQUARE BUTTON 00326 { 00327 if(cfg==0) 00328 { 00329 display_time = t.read_ms(); 00330 display_status=1; 00331 clear_lcd(); 00332 if(eth_led1 == 1) 00333 display.printf("%-16s%-16s",eth.getIPAddress(),eth.getName()); 00334 else 00335 display.printf("ETH DISCONNECTED"); 00336 } 00337 else 00338 { 00339 reset_config(); 00340 } 00341 } 00342 if(byte_read=='A')//UP BUTTON 00343 { 00344 display_status=0; 00345 if(cfg==0) //If not in CONFIG mode 00346 { 00347 display_time = t.read_ms(); 00348 clear_lcd(); 00349 LCD_index = (LCD_index+1)%8; //increment LCD index 00350 write_LCD(); //write to LCD 00351 } 00352 else //If CONFIG mode 00353 { 00354 if(CH[LCD_index].limit+mult <= CURR_MAX_LIMIT) //Verify higher current bound condition 00355 CH[LCD_index].limit = CH[LCD_index].limit + mult; //Use multiplier to increment current 00356 display.putc(0xFE); 00357 display.putc(0x47); 00358 display.putc(0xC); 00359 display.putc(0x2); 00360 display.printf("%3.2f",CH[LCD_index].limit); 00361 display.putc(0xFE); 00362 display.putc(0x47); 00363 if(cfg==1) //if config = 1, blink first digit 00364 display.putc(0xB+cfg); 00365 else //else, blink second or third digit (after dot) 00366 display.putc(0xC+cfg); 00367 display.putc(0x2); 00368 } 00369 00370 } 00371 if(byte_read=='C')//DOWN BUTTON 00372 { 00373 display_status=0; 00374 if(cfg==0) //If not in CONFIG mode 00375 { 00376 display_time = t.read_ms(); 00377 clear_lcd(); 00378 LCD_index = (LCD_index-1); //decrement LCD index 00379 if(LCD_index==-1) //Verify lower bound 00380 LCD_index = 7; 00381 write_LCD(); //write to LCD 00382 } 00383 else //If CONFIG mode 00384 { 00385 if(mult<=CH[LCD_index].limit) //Verify lower current bound condition 00386 CH[LCD_index].limit = CH[LCD_index].limit - mult; //Use multiplier to decrement current 00387 display.putc(0xFE); 00388 display.putc(0x47); 00389 display.putc(0xC); 00390 display.putc(0x2); 00391 display.printf("%3.2f",CH[LCD_index].limit); 00392 display.putc(0xFE); 00393 display.putc(0x47); 00394 if(cfg==1) //if config = 1, blink first digit 00395 display.putc(0xB+cfg); 00396 else //else, blink second or third digit (after dot) 00397 display.putc(0xC+cfg); 00398 display.putc(0x2); 00399 } 00400 } 00401 if(byte_read=='D')//DOWN SQUARE BUTTON 00402 { 00403 if(cfg<4&&display_status==0) //If CONFIG<4, go to next config 00404 { 00405 led_cfg=1; //turn config led on 00406 cfg = cfg++; //increment config variable 00407 mult = mult/10; //adjust multiplier (divided by 10 each config increment) 00408 display.putc(0xFE); 00409 display.putc(0x47); 00410 if(cfg==1) //if config = 1, blink first digit 00411 display.putc(0xB+cfg); 00412 else //else, blink second or third digit (after dot) 00413 display.putc(0xC+cfg); 00414 display.putc(0x2); 00415 display.putc(0xFE); 00416 display.putc(0x53); 00417 } 00418 if(cfg>=4) //If config >=4, configuration end 00419 { 00420 reset_config(); 00421 } 00422 } 00423 } 00424 } 00425 } 00426 00427 void reset_config(void) 00428 { 00429 led_cfg=0; //turn config led off 00430 cfg=0; //reset config variable 00431 mult = 10; 00432 //reset mult to standard value = 10 00433 adj_ilimit(LCD_index+1,CH[LCD_index].limit); //adjust current limit 00434 00435 new_cfg=1; 00436 save_cfg_time=t.read_ms(); 00437 display.putc(0xFE); 00438 display.putc(0x54); 00439 } 00440 00441 //message incoming treatment - Socket EPICS 00442 void message_treatment(void) 00443 { 00444 ch_msg_idx = socket_buffer[0] - 0x30; //First character is the channel number 00445 if(ch_msg_idx>0 && ch_msg_idx<=8) //drop if out of range 00446 { 00447 ch_msg_idx--; //decrement to index 0 to 7 00448 if(socket_buffer[1]=='r') //read message 00449 { 00450 n = sprintf(send_buffer,"OK>%d:\tV=%4.2f\tI=%3.2f\tC=%.1f\tIL=%3.2f\tF=%d\tOL=%d\tNL=%d\tE=%d\r\n",ch_msg_idx+1,\ 00451 CH[ch_msg_idx].voltage,CH[ch_msg_idx].current,\ 00452 CH[ch_msg_idx].control,CH[ch_msg_idx].limit,\ 00453 CH[ch_msg_idx].failure,CH[ch_msg_idx].overload>ERROR_REP,\ 00454 CH[ch_msg_idx].noload>ERROR_REP,CH[ch_msg_idx].enable); 00455 return; 00456 } 00457 if(socket_buffer[1]=='l') //current limit message 00458 { 00459 if(socket_buffer[2]=='?') //get 00460 { 00461 n = sprintf(send_buffer,"OK>%d:\tIL=%3.2f\r\n",ch_msg_idx+1,CH[ch_msg_idx].limit); 00462 return; 00463 } 00464 if(socket_buffer[3]=='.') //set (must be in 3.2f format) 00465 { 00466 ilimit_msg = (socket_buffer[2]-0x30) + (socket_buffer[4]-0x30)/10.0 + (socket_buffer[5]-0x30)/100.0; //convert three digits to float 00467 if(ilimit_msg > 0 && ilimit_msg <= CURR_MAX_LIMIT) //verifiy bounds 00468 { 00469 CH[ch_msg_idx].limit = ilimit_msg; 00470 ilimit_msg = ilimit_msg*I_K+I_OFF; //Convert to voltage 00471 do{ 00472 tx.data = int((0xFFF*ilimit_msg)/5)&0xFFF; //Convert to 12 bit data 00473 register_amc=DAC0+ch_msg_idx; //set register 00474 write_U4(); 00475 read_U4(); 00476 }while(tx.data!=rx.data); //try to write until success. (main thread also using SPI) 00477 00478 n = sprintf(send_buffer,"OK>%d:\tIL=%3.2f\r\n",ch_msg_idx+1,CH[ch_msg_idx].limit); 00479 new_cfg=1; //new cfg file must be written by the main loop 00480 save_cfg_time = t.read_ms(); 00481 return; 00482 } 00483 else 00484 { 00485 n = sprintf(send_buffer,"ERROR>%5.2f out of range\r\n",ilimit_msg); 00486 return; 00487 } 00488 } 00489 } 00490 if(socket_buffer[1]=='e') //enable message 00491 { 00492 if(socket_buffer[2]=='?') //get method 00493 { 00494 n = sprintf(send_buffer,"OK>%d:\tE=%d\r\n",ch_msg_idx+1,CH[ch_msg_idx].enable); 00495 return; 00496 } 00497 if(socket_buffer[2]=='1') //set method (enable=1) 00498 { 00499 do{ 00500 register_amc = GPIO; //set GPIO register 00501 read_U5(); //read register 00502 tx.data = rx.data | (0b1<<ch_msg_idx); 00503 write_U5(); //write the 1 position 00504 read_U5(); 00505 }while(tx.data != rx.data); //try to write until success. (main thread also using SPI) 00506 CH[ch_msg_idx].enable = 1; 00507 new_cfg=1; 00508 save_cfg_time=t.read_ms(); 00509 n = sprintf(send_buffer,"OK>%d:\tE=%d\r\n",ch_msg_idx+1,CH[ch_msg_idx].enable); 00510 return; 00511 } 00512 if(socket_buffer[2]=='0') //set method (enable=0) - Disable 00513 { 00514 do{ 00515 register_amc = GPIO; //set GPIO register 00516 read_U5(); //read register 00517 tx.data = rx.data & ~(0b1<<ch_msg_idx); 00518 write_U5(); //write the 0 position 00519 read_U5(); 00520 }while(tx.data != rx.data); //try to write until success. (main thread also using SPI) 00521 CH[ch_msg_idx].enable = 0; 00522 new_cfg=1; 00523 save_cfg_time=t.read_ms(); 00524 n = sprintf(send_buffer,"OK>%d:\tE=%d\r\n",ch_msg_idx+1,CH[ch_msg_idx].enable); 00525 return; 00526 } 00527 } 00528 } 00529 if(socket_buffer[0]=='p'&&socket_buffer[1]=='i'&&socket_buffer[2]=='n'&&socket_buffer[3]=='g') //ping message 00530 { 00531 n = sprintf(send_buffer,"OK>pong\r\n"); //answer pong 00532 return; 00533 } 00534 if(socket_buffer[0]=='v') //firmware version 00535 { 00536 n = sprintf(send_buffer,"OK>firmware version = %s\r\n",VERSION); 00537 return; 00538 } 00539 if(socket_buffer[0]=='n') //device name 00540 { 00541 if(socket_buffer[1]=='?') 00542 { 00543 n = sprintf(send_buffer,"OK>device name = %s\r\n",dev_name); 00544 return; 00545 } 00546 if(socket_buffer[1]=='=') 00547 { 00548 n=0; 00549 while(socket_buffer[n+2]!='\0'&&n<=20) 00550 { 00551 dev_name[n]=socket_buffer[n+2]; 00552 n++; 00553 } 00554 dev_name[n]='\0'; 00555 new_cfg=1; 00556 save_cfg_time=t.read_ms(); 00557 n = sprintf(send_buffer,"OK>device name = %s\r\n",dev_name); 00558 return; 00559 } 00560 00561 } 00562 if(socket_buffer[0]=='r'&&socket_buffer[1]=='e'&&socket_buffer[2]=='s'&&socket_buffer[3]=='e'&&socket_buffer[4]=='t') //reset messag 00563 { 00564 n = sprintf(send_buffer,"OK>rebooting...\r\n"); //answer 00565 client.send_all(send_buffer,n); 00566 wait_ms(500); 00567 mbed_reset(); //reset function 00568 return; 00569 } 00570 n = sprintf(send_buffer,"ERROR> NOT-A-CMD\r\n\0"); //command not found 00571 } 00572 00573 void main_loop(void) //main thread (real-time priority) - read and write AMC devices 00574 { 00575 while(1){ 00576 00577 if(flag_end_u5) //Wait U5 end of convertion 00578 { 00579 flag_end_u5 = 0; //Reset flag 00580 00581 register_amc = ADC0; //reads U5 ADC0 00582 fast_read_U5(); 00583 for(i=0;i<=7;i++) 00584 { 00585 register_amc = ADC0+i+1; //reads U5 ADC1 + i 00586 fast_read_U5(); 00587 00588 CH[i].current = FILTC*CH[i].current + FILTC2*(((rx.data*5.0)/0xFFF)-I_OFF)/I_K; //store current of the previous channel 00589 if(CH[i].current<0) //negative current not allowed 00590 CH[i].current=0; 00591 } 00592 00593 } 00594 00595 if(flag_end_u4) //Wait U4 end of convertion 00596 { 00597 flag_end_u4 = 0; //Reset flag 00598 00599 register_amc = ADC0; //reads U4 ADC0 00600 fast_read_U4(); 00601 for(i=0;i<=7;i++) 00602 { 00603 register_amc = ADC8+i; //reads U4 ADC8 + i (ADC8 to ADC15) 00604 fast_read_U4(); 00605 00606 CH[i].voltage = FILTC*CH[i].voltage+FILTC2*((rx.data*5.0)/0xFFF)/V_K; //store voltages (previous convertions - ADC0 to ADC7) 00607 if(CH[i].voltage<0) //negative voltage not allowed 00608 CH[i].voltage = 0; 00609 00610 //Failure output triggered by NO LOAD or OVERLOAD 00611 //Determine overload via software (above 90% current limit) 00612 if(CH[i].current > CH[i].limit*0.85) 00613 { 00614 if(CH[i].overload<=2*ERROR_REP) //verify counter limit 00615 CH[i].overload++; //Increment overload counter 00616 if(CH[i].overload>=ERROR_REP) //Digital Filtering by repetitive overload diagnostics 00617 fail_out(i+1,1); //Set failure output 00618 } 00619 else 00620 { 00621 if(CH[i].overload>0) 00622 CH[i].overload--; //decrement overload counter 00623 if(CH[i].overload<ERROR_REP) //verify overload condition 00624 if(CH[i].noload<ERROR_REP) //verify no load condition 00625 fail_out(i+1,0); //Reset failure output 00626 00627 } 00628 //Determine no load via software (Resistance over 150 ohm) 00629 if(CH[i].voltage > 2 && CH[i].current < CH[i].voltage/150) 00630 { 00631 if(CH[i].noload<=2*ERROR_REP) //verify counter limit 00632 CH[i].noload++; //Increment no load counter 00633 if(CH[i].noload>=ERROR_REP) //Digital Filtering by repetitive no load diagnostics 00634 fail_out(i+1,1); //Set failure output 00635 } 00636 else 00637 { 00638 if(CH[i].noload>0) 00639 CH[i].noload--; //decrement no load counter 00640 if(CH[i].noload<ERROR_REP) //verify no load condition 00641 if(CH[i].overload<ERROR_REP) //verify overload condition 00642 fail_out(i+1,0); //Reset failure output 00643 } 00644 00645 register_amc = ADC0+i+1; //Read next ADC (ADC0 to ADC7) 00646 fast_read_U4(); 00647 00648 //Estimate control input (Duty cycle in %) 00649 CH[i].control = FILTC*CH[i].control+FILTC2*(rx.data*VC_K*5.0/0xFFF+VC_OFF); 00650 00651 #ifndef CAL 00652 //Verify limits 00653 if(CH[i].control<0) 00654 CH[i].control=0; 00655 if(CH[i].control>100) 00656 CH[i].control=100; 00657 #endif 00658 } 00659 DEBUG_PRINTF("Duty Cycle Calibration - Measured Voltage: %f",rx.data*5.0/0xFFF); 00660 } 00661 } 00662 } 00663 00664 //initiate socket instances 00665 void socket_start() 00666 { 00667 server.set_blocking(true); // Set socket connection not blocking 00668 client.set_blocking(false,50); 00669 server.bind(PORT); // TCP Socket setup 00670 server.listen(2); // Socket Server start listening request. 00671 } 00672 00673 00674 //Server loop (thread triggered) 00675 void server_loop(void) 00676 { 00677 while(1) 00678 { 00679 httpsvr.run(&CH[0],dev_name); //wait for new client connection 00680 server_led = !server_led; //togle server led 00681 } 00682 } 00683 00684 //Socket loop (thread triggered) - for EPICS 00685 void socket_loop(void) 00686 { 00687 00688 while(1) 00689 { 00690 socket_led = !socket_led; //toggle socket LED 00691 00692 if(server.accept(client)!=-1) //blocks waiting for a new client 00693 { 00694 client.set_blocking(false,50); // Set client connection not blocking 00695 while(client.is_connected()) // while connected 00696 { 00697 socket_led = !socket_led; //toggle LED again (fast flash) 00698 receive_return = client.receive_all(socket_buffer,200); //receive all messages 00699 if(receive_return>0) //if bytes received 00700 { 00701 message_treatment(); //treat message 00702 client.send_all(send_buffer,n); //send answer 00703 } 00704 if(receive_return < 0) //if erro, break connection 00705 break; 00706 } 00707 client.close(); //finally close the client 00708 } 00709 } 00710 } 00711 00712 //AMC7812B setup (U4 and U5) 00713 void amc_setup(void){ 00714 00715 cs_u4 = 1; //Chip Select must be deselected 00716 cs_u5 = 1; //Chip Select must be deselected 00717 dac_clr = 1; //DAC Clear inactive 00718 amc_reset = 1; //Reset Inactive 00719 cnvt_u5 = 1; //U5 Convertion not triggered 00720 cnvt_u4 = 1; //U4 Convertion not triggered 00721 00722 //Reset AMC7812B to make sure both are in the initial state 00723 amc_reset = 0; 00724 wait_ms(5); 00725 amc_reset = 1; 00726 00727 // Setup the spi for 12 bit data, high steady state clock, 00728 // second edge capture, with a 10MHz clock rate 00729 spi.format(12,1); 00730 spi.frequency(10000000); 00731 00732 wait_ms(10); //Wait AMC7812B power up 00733 00734 //Disabling Power Down Register 00735 tx.data = 0x7FFE; 00736 register_amc = PWR_DOWN; 00737 write_U4(); 00738 write_U5(); 00739 00740 //Set all ADC range 0 to 5V 00741 tx.data = 0xFFFF; 00742 register_amc = ADC_GAIN; 00743 write_U4(); 00744 write_U5(); 00745 00746 //Set all u4 16 ADC channels active 00747 register_amc = ADC_CH0; 00748 tx.data = 0x6DFF; 00749 write_U4(); 00750 register_amc = ADC_CH1; 00751 tx.data = 0x7000; 00752 write_U4(); 00753 00754 //Set u5 first 8 ADC channels active 00755 tx.data = 0x6DE0; 00756 register_amc = ADC_CH0; 00757 write_U5(); 00758 00759 //Disable LT, D1 and D2 00760 tx.data = 0x0000; 00761 register_amc = T_CONF; 00762 write_U4(); 00763 write_U5(); 00764 00765 tx.data = 0x0400; //Set both in direct mode 00766 //tx.data = 0x2400; //Set both in auto mode 00767 register_amc = CONF0; 00768 write_U4(); 00769 write_U5(); 00770 00771 tx.data = 0x0300; //Set convertion ate to 62.5kS/s (auto mode) 00772 register_amc = CONF1; 00773 write_U4(); 00774 write_U5(); 00775 00776 } 00777 00778 //Adjust current limit 00779 // 00780 // Parameters: 00781 // - int channel: channel to adjust (from 1 to 8) 00782 // - float value: current value 00783 // 00784 void adj_ilimit(int channel,float value) //channel from 1 to 8 00785 { 00786 if(value > CURR_MAX_LIMIT) //current allowed up to CURR_MAX_LIMIT 00787 value = CURR_MAX_LIMIT; 00788 00789 value = value*I_K+I_OFF; //Convert to voltage 00790 00791 tx.data = int((0xFFF*value)/5)&0xFFF; //Convert to 12 bit data 00792 register_amc=DAC0+channel-1; //set register 00793 write_U4(); //write U4 AMC7812B DAC 00794 } 00795 00796 //Set/Reset Failure Output 00797 // 00798 // Parameters: 00799 // - int channel: channel to adjust (from 1 to 8) 00800 // - int value: output 5V (value=1) or 0V (value=0) 00801 // 00802 void fail_out(int channel,int value)//channel from 1 to 8 00803 { 00804 tx.data = 0xFFF*value; //set 12bit data to DAC 00805 register_amc=DAC0+channel-1; //set register 00806 write_U5(); //write U5 AMC7812B 00807 CH[channel-1].failure = value; //update data structure 00808 } 00809 00810 //U4 end of convertion Interrupt 00811 void end_conv_u4(void){ 00812 flag_end_u4 = 1; //set U4 flag 00813 } 00814 00815 //U5 end of convertion Interrupt 00816 void end_conv_u5(void){ 00817 flag_end_u5 = 1; //set U5 flag 00818 } 00819 00820 //Trigger Both (U4 and U5) AD convertions 00821 void trigger_conv(void){ 00822 00823 //Triggering ADC via software - Setting flag ICONV inside CONF register 00824 /* 00825 register_amc = CONF0; 00826 read_U4(); 00827 tx.data = rx.data | 0x1000; 00828 write_U4(); 00829 00830 read_U5(); 00831 tx.data = rx.data | 0x1000; 00832 write_U5(); 00833 */ 00834 00835 //Triggering ADC via hardware - CONV pin active low. 00836 cnvt_u5 = 0; 00837 cnvt_u4 = 0; 00838 00839 cnvt_u5 = 1; 00840 cnvt_u4 = 1; 00841 00842 } 00843 00844 //Trigger U4 convertion 00845 void trigger_u4(void) 00846 { 00847 cnvt_u4 = 0; 00848 cnvt_u4 = 1; 00849 } 00850 00851 //Trigger U5 convertion 00852 void trigger_u5(void) 00853 { 00854 cnvt_u5 = 0; 00855 cnvt_u5 = 1; 00856 } 00857 00858 //U5 Fast Read Function 00859 //fast_read saves always the previous read value in rx.data 00860 //See AMC7812B datasheet for more details 00861 void fast_read_U5(void){ 00862 cs_u5 = 0; // Select the device by seting chip select low 00863 00864 reg_aux = spi.write((register_amc|0x80)<<4); 00865 rx.data = (reg_aux&0xF)<<12; 00866 reg_aux = spi.write(0x000); 00867 rx.data = rx.data|(reg_aux&0xFFF); 00868 00869 cs_u5 = 1; // Deselect the device by seting chip select low 00870 } 00871 00872 //U4 Fast Read Function 00873 //fast_read saves always the previous read value in rx.data 00874 //See AMC7812B datasheet for more details 00875 void fast_read_U4(void){ 00876 cs_u4 = 0; // Select the device by seting chip select low 00877 00878 reg_aux = spi.write((register_amc|0x80)<<4); 00879 rx.data = (reg_aux&0xF)<<12; 00880 reg_aux = spi.write(0x000); 00881 rx.data = rx.data|(reg_aux&0xFFF); 00882 00883 cs_u4 = 1; // Deselect the device by seting chip select low 00884 } 00885 00886 //U5 SPI read function 00887 //Read two times to assure the second read will save the first read result in rx.data 00888 //Takes about two times the fast_read function 00889 void read_U5(void){ 00890 cs_u5 = 0; // Select the device by seting chip select low 00891 00892 spi.write((register_amc|0x80)<<4); 00893 spi.write(0x000); 00894 cs_u5 = 1; // Deselect the device by seting chip select low 00895 cs_u5 = 0; // Select the device by seting chip select low 00896 reg_aux = spi.write((register_amc|0x80)<<4); 00897 rx.data = (reg_aux&0xF)<<12; 00898 reg_aux = spi.write(0x000); 00899 rx.data = rx.data|(reg_aux&0xFFF); 00900 00901 cs_u5 = 1; // Deselect the device by seting chip select low 00902 } 00903 00904 //U4 SPI read function 00905 //Read two times to assure the second read will save the first read result in rx.data 00906 //Takes about two times the fast_read function 00907 void read_U4(void){ 00908 cs_u4 = 0; // Select the device by seting chip select low 00909 00910 spi.write((register_amc|0x80)<<4); 00911 spi.write(0x000); 00912 cs_u4 = 1; // Deselect the device by seting chip select low 00913 cs_u4 = 0; // Select the device by seting chip select low 00914 reg_aux = spi.write((register_amc|0x80)<<4); 00915 rx.data = (reg_aux&0xF)<<12; 00916 reg_aux = spi.write(0x000); 00917 rx.data = rx.data|(reg_aux&0xFFF); 00918 00919 cs_u4 = 1; // Deselect the device by seting chip select low 00920 } 00921 00922 //U4 SPI write function 00923 void write_U4(void){ 00924 00925 cs_u4 = 0; // Select the device by seting chip select low 00926 reg_aux = register_amc<<4|((tx.data&0xF000)>>12); 00927 spi.write(reg_aux); 00928 spi.write(tx.data&0xFFF); 00929 cs_u4 = 1; // Deselect the device by seting chip select low 00930 } 00931 00932 //U5 SPI write function 00933 void write_U5(void){ 00934 cs_u5 = 0; // Select the device by seting chip select low 00935 reg_aux = register_amc<<4|((tx.data&0xF000)>>12); 00936 spi.write(reg_aux); 00937 spi.write(tx.data&0xFFF); 00938 cs_u5 = 1; // Deselect the device by seting chip select low 00939 } 00940 00941 //Initialize variables and LCD 00942 void setup(){ 00943 00944 //Auxiliary variables 00945 int aux; 00946 char c; 00947 float tmp_lim; 00948 int tmp_en; 00949 uint8_t gpio_init=0; 00950 00951 phy_rst = 0; //reset ethernet Phy 00952 eth_led1 = 0; //turn off ethernet led 1 00953 eth_led2 = 0; //turn off ethernet led 2 00954 phy_rst = 1; //Power on ethernet Phy 00955 00956 display.baud(19200); 00957 00958 //Clear all display LEDs 00959 display.putc(0xFE); 00960 display.putc(0x5A); 00961 display.putc(0x00); 00962 display.putc(0x00); 00963 display.putc(0xFE); 00964 display.putc(0x5A); 00965 display.putc(0x01); 00966 display.putc(0x00); 00967 display.putc(0xFE); 00968 display.putc(0x5A); 00969 display.putc(0x02); 00970 display.putc(0x00); 00971 00972 //Set display contrast 00973 display.putc(0xFE); 00974 display.putc(0x91); 00975 display.putc(0x80); 00976 00977 //Config file handler 00978 cfg_file = fopen("/local/lim.cfg", "r"); // Open "lim.cfg" on the local file system for reading 00979 if(cfg_file==NULL) //If config file doesnt exist, create new file 00980 { 00981 cfg_file = fopen("/local/lim.cfg", "w"); //Open "lim.cfg" on the local file system for writing 00982 fprintf(cfg_file,"Channel Configuration - Current Limit and Enable\n"); 00983 fprintf(cfg_file,"%s\n",DEVICE_NAME); 00984 strcpy(dev_name,DEVICE_NAME); 00985 for(i=0;i<8;i++) 00986 { 00987 CH[i].limit = DEFAULT_CURR_LIMIT; //Save default current limit in all channels 00988 fprintf(cfg_file,"%d %3.2f 1\n",i+1,DEFAULT_CURR_LIMIT); //Write to file 00989 CH[i].enable = 1; 00990 } 00991 ERROR_PRINTF("lim.cfg file not found! Creating default file..."); 00992 } 00993 else //File exists :) 00994 { 00995 do{ 00996 c = getc(cfg_file); 00997 }while(c!='\n'); //Linescan (scan until \n) 00998 fscanf(cfg_file,"%s",dev_name); //Read name string 00999 for(i=0;i<8;i++) //Read 8 channels 01000 { 01001 fscanf(cfg_file,"%d %f %d",&aux,&tmp_lim,&tmp_en); //Read channel and limit value 01002 if(tmp_lim<0||tmp_lim>CURR_MAX_LIMIT) //Verify limits 01003 tmp_lim=DEFAULT_CURR_LIMIT; //If tmp is above limit, use default 01004 CH[i].limit = tmp_lim; //set channel limit 01005 CH[i].enable = tmp_en&0x1; 01006 } 01007 } 01008 fclose(cfg_file); //close config file 01009 gpio_init=0; 01010 for(i=0;i<8;i++) //set structure variables 01011 { 01012 CH[i].noload = 0; //no load variable 01013 CH[i].overload = 0; //oveload variable 01014 fail_out(i+1,0); //reset failure output 01015 adj_ilimit(i+1,CH[i].limit); //adjust current limit 01016 gpio_init = gpio_init | (CH[i].enable&0x1)<<i; 01017 } 01018 01019 write_LCD(); //write to LCD 01020 01021 reset_config(); //reset configuration 01022 flag_end_u4=0; //reset U4 end of convertion flag 01023 flag_end_u5=0; //reset U5 end of convertion flag 01024 01025 //set GPIO aoutput high (enable) 01026 tx.data = gpio_init; 01027 //enable all channels (hardware GPIO) 01028 register_amc = GPIO; 01029 write_U5(); 01030 01031 } 01032 01033 //Clear LCD Function 01034 void clear_lcd(){ 01035 display.putc(0xFE); 01036 display.putc(0x58); 01037 } 01038 01039 //Set Red Led - Error 01040 void error(){ 01041 display.putc(0xFE); 01042 display.putc(0x5A); 01043 display.putc(0x00); 01044 display.putc(0x02); 01045 } 01046 01047 //Set Green Led - Normal 01048 void normal(){ 01049 display.putc(0xFE); 01050 display.putc(0x5A); 01051 display.putc(0x00); 01052 display.putc(0x01); 01053 } 01054 01055 //Set Red and Green - Disabled 01056 void disabled(){ 01057 display.putc(0xFE); 01058 display.putc(0x5A); 01059 display.putc(0x00); 01060 display.putc(0x03); 01061 } 01062 01063 //Write channel index to LCD 01064 void write_LCD() 01065 { 01066 if(CH[LCD_index].failure == 1) 01067 error(); //error status if failure 01068 else 01069 { 01070 if(CH[LCD_index].enable == 0) 01071 disabled(); //disabled status if not enabled 01072 else 01073 normal(); //Normal mode 01074 } 01075 clear_lcd(); //Clear LCD 01076 display.printf("CH%d %5.2fV/%3.2fAC:%03.0f%% IL:%3.2fA",LCD_index+1,CH[LCD_index].voltage,CH[LCD_index].current,CH[LCD_index].control,CH[LCD_index].limit); 01077 } 01078 01079 //Heartbeat toogle MBED led function 01080 void heart(){ 01081 blink = !blink; //toggle blink led 01082 }
Generated on Wed Jul 13 2022 07:45:45 by
1.7.2