niedziela, 25 listopada 2012

Book-sized PC - alive.

I'm back after some time of being occupied by other tasks, that were not worthy of being published here ;-). I have completed my book-sized industrial PC.

I have received this machine some time ago from a friend of mine. It was used in his company in some complicated systems, and had it's BIOS exchanged for a custom one. This was the first and only big problem about this machine. I have tried exchanging the BIOS from the 'inside' using AWDFlash, but with no success, so I had to ask the same friend for more help - he burned the EEPROM with a proper BIOS *.bin file using a EEPROM burner. Now it worked, so I only had to install the OS (Win XP Proffesional SP2) and all drivers.


For this PC I have obtained (from ebay) a Nvidia Quadro NVS 200 PCI graphics card (64 MB) capable of feeding two VGAs (I'm currently using one, but plan to use two, why not). Apart from that - Pentium III 633 MHz (overclocked 550 MHZ Coppermine) and 512 MB of RAM (chipsets maximum unfortunately). The more interesting part of the PC is the I/O PCI card that I have added - seen on top. This is an DIO card (Digital I/O) - 16 relay inputs and 16 photo-isolated inputs. This will go very well with the whole array of ports the card has: four serials (RS-232/422/485 configurable), two parallels and two USBs.


The PC is quite compact, so I guess there will be some trouble with heat inside, especially when I will exchange the processor for a PIII Tualatin (preferably 1400 MHz PIII-S version) - this is the only upgrade that is still pending due to the lack of a suitable CPU, and general scarceness of such. Still this is a great addition to my collection and one of few that has potential application (but I do not want to say anything about that for now, as the grant proposal is sent but not graded by now). Next addition to this setup is a touch-screen LCD. It has a cool RS-232 interface, so it should not be hard to put it together. The harder part is to put the touch-screen part and the LCD part together without breaking anything. I have to find proper tape for mending it together and a foam spacer tape for making a spacer between the LCD and touch-screen.


I would like to thank again the 'anonymous' donors: of this machine and many more things ;-) for donating my collection with extremely nice hardware and helping me put it together.

poniedziałek, 20 sierpnia 2012

RTCU datalogger cont.

Okay, so as I wrote in the last post I had to modify the code in order to get any possibility apart from datalogging. I used asynchronous function blocks in order to get the 1-Wire communication in a separate thread-like entity.

 FUNCTION_BLOCK ASYNC Temp_DS1820;  
 VAR_INPUT  
   family : int;  
   kill : bool;  
 END_VAR;  
 VAR_OUTPUT  
   temp_calk, temp_ulam : int;  
 END_VAR;  

After that you have only to define a variable of type Temp_DS1820 and voila. To write the temperature into a file I use fsFileWriteStringNL and get the output variables out of the variable connected with the function block

 fsFileWriteStringNL(fd:=file_id, str:=temp="+intToStr(v:=temperature.temp_calk)+","+intToStr(v:=temperature.temp_ulam));  

Making the function block asynchronous makes it a separate thread without using a real thread. You only have to remember to put everything in the function block into a loop (I used while not kill do <...> end_while, so I can 'kill' this 'thread' whenever I want to) to work constantly.

This way I achieved ~15 times faster execution of the main program loop (that was only writing the temp into the file every 60 s) in the main program. This means that one can do tons of other things instead of waiting for ~700 ms to convert the temperature. Such approach can, of course, be used for various other applications that require the program to wait. RTCU DX4 is capable of multithreading so let's use it.

RTCU data logger

In this example I used a DS1820 1-Wire temperature sensor. The temperature is read from the sensor and written in a ASCII file on the SD-Card in the RTCU. Here's the code

 PROGRAM a1wire;  
 // These are the local variables of the program block  
 VAR  
   ow_dev : int;  
   sign : sint;  
   family : int;  
   dane_sint1, dane_sint2 : sint;  
   dane_int1, dane_int2 : int;  
   temp_calk, temp_ulam : int;  
   file_id : file;  
 END_VAR;  
   ow_dev:=owSearchX(first:=0, last:=255, reset:=true); // Scan the 1-Wire network  
   DebugMsg(message:=intToStr(v:=ow_dev)); // Number of 1-Wire devices in our case it is 1  
   family:=owGetFamily(device:=1); // Get the family name of the device  
   DebugMsg(message:=intToStr(v:=family)); // Family name of the device  
   DebugMsg(message:=owGetID(family:=family, device:=1)); // Get the 64bit ID of the device  
   if fsMediaPresent(media:=0) and (fsMediaOpen(media:=0)=0) then fsMediaQuickFormat(media:=0); fsDirCreate(name:="test"); fsDirChange(path:="A:\test"); fsFileClose(fd:=fsFileCreate(name:="test.txt")); fsMediaClose(media:=0); DebugMsg(message:="file created"); end_if; // if media is present and opened create a directory and go inside  
   fsMediaOpen(media:=0); // Open SD-Card  
   displayClear();  
 BEGIN  
   // Code from this point until END will be executed repeatedly  
   owAccess(family:=family, device:=1); // Acces the DS1820  
   owWrite(data:=16#44); // Order the DS1820 to convert temperature  
   Sleep(delay:=700); // Wait for 700 ms (DS1820 datasheet says tha this should be at least 750ms, but 700ms work for this particular DS1820)  
   owRelease(); // Release the 1-Wire network  
   owAccess(family:=family, device:=1); // Acces it again  
   owWrite(data:=16#BE); // Order the DS1820 to send the scratchpad content  
   owRead(data:=dane_sint1); // Read LSB   
   owRead(data:=dane_sint2); // Read MSB  
   if dane_sint1<0 then // Convert the temperature  
    sign:=64;   
    else   
      sign:=0;   
    end_if;  
   temp_calk:= shr8(in:=shl8(in:=dane_sint1, n:=1), n:=2)+sign;  
   if dane_sint2 <> 0 then // Get the sign of the temperature  
    temp_calk:=temp_calk*-1;   
    end_if;  
   temp_ulam:= 5*(dane_sint1 mod 2); // Calculate the fractional part of the temperature  
   owRelease(); // Release the 1-Wire network  
   if fsMediaOpen(media:=0)=0 then // Open the SD-Card  
    file_id := fsFileOpen(name:="a:\test\test.txt"); // Open file  
    if fsFileStatus(fd:=file_id) = 0 then // If file is opened...  
      DebugMsg(message:="file write status "+ intToStr(v:=fsFileWriteStringNL(fd:=file_id, str:="temp="+intToStr(v:=temp_calk)+","+intToStr(v:=temp_ulam)))); // ...write a string in it  
      fsFileClose(fd:=file_id); // Close the file  
      end_if;  
    end_if;  
   displayString(message:="temp="+intToStr(v:=temp_calk)+","+intToStr(v:=temp_ulam)); // Display the temperature  
 END;  
 END_PROGRAM;  

And it works! producing a test.txt file with

temp=28,0
temp=28,5
temp=28,5
etc...

Okay, that's great, but hey - I used the whole controller capacity for that. Every single run of the software takes ~1s (mainly due to the fact that I'm waiting for the temperature conversion for 700ms). So the next thing to do is to put the temperature reading from the 1-Wire sensor into a asynchronous functionblock or another thread, as this controller is able to multithread. Stay tuned for that, as I guess it will take me a bit to do ;-).

And I would like to thank Stanko, for help with calculating the temperature from the 1-Wire data :-).