Saturday, May 30, 2009

Lessons learned

A few tricks I found recently on my own, worth sharing:

1. I learned the hard way that a good practice when one does prototyping (or first revisions) is to leave some breakout regions in the board; in case an extra component or a connector needs to be included, there is room for it; otherwise, one may end up with kludges like the one in the photo below.


2. Spacers, those expensive small plastic cillinders, with a screw through them, used for tightening 2 boards together: make them from discarded pens, just cut to the desired length. I used them in my Wide Clock.

3. Battery holders can be attached to the case with velcro. One can use velcro even for boards.

4. Push buttons that look similar may be oppositely different, that is, one closes the circuit, the other opens it. The latter is sometimes called "touch button". So, be careful and make sure you use the one you intend to.

(to be continued)

Friday, May 22, 2009

Arduino writes to file

One of the frequently asked question on the Arduino forum is "how can Arduino save data to a file?" (see this thread for example). The quick answer is this: Arduino sends data over the serial port to the PC, which, in turn, is running an executable that reads the serial port. Every byte of data (or ASCII character) received is then saved to a file. So, this mechanism has two parts:
1. a piece of the sketch, running on Arduino, will send data using the function Serial.print();
2. a piece of code (executable, script etc) running on PC, will receive data from the serial port.

An example of VBscript that does just that is shown below. The characters read from COM6 (baud rate 9600, 8 bits, no parity, 1 stop bit) are saved to file "C:\results.txt".

Const ForReading = 1
Const ForWriting = 2

Set fso = CreateObject("Scripting.FileSystemObject")
Set com = fso.OpenTextFile("COM6:9600,N,8,1", ForReading)

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\results.txt", ForWriting, True)

MsgBox("Start to read data from COM")

Do While com.AtEndOfStream <> True
s = com.ReadLine
objFile.WriteLine(s)
WScript.Sleep(200)
Loop

objFile.Close
com.Close()

A similar approach can be used for reading characters from a file.

The following is an example VBscript that reads the characters from a text file ("C:\docs\quotes.txt") and sends them on port COM7(9600,N,8,1) to Arduino. I use it to load text messages (quotations) to an external EEPROM (24LC256).


Const ForReading = 1
Const ForWriting = 2

'------------------------------------------------------------------------------------------------
' open USB serial port (COMx);
'
' If the serial monitor in Arduino IDE is open, you will get an "access denied" error.
' Just make sure that the serial monitor is closed (so bytes are not sent by the arduino board).
'------------------------------------------------------------------------------------------------

Set fso = CreateObject("Scripting.FileSystemObject")
Set com = fso.OpenTextFile("COM7:9600,N,8,1", ForWriting)


'---------------------------------------------
' read content of text file line by line;
' write line to COMx;
'---------------------------------------------

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\docs\quotes.txt", ForReading)

MsgBox("Ready to write file content to COM")

Do While objFile.AtEndOfStream <> True
'---------------------------------------------------------------------------------------------------------
' read 10 characters at a time; arduino serial buffer cannot take more than 32 characters;
' writing a character to eeprom takes about 11 ms (assuming that there is no serial.prints in the loop);
' therefore, after each batch of 10 chars sent to COM, we should wait no less than 110 ms;
' we use 200 to have a margin of safety;
'---------------------------------------------------------------------------------------------------------
strChars = objFile.Read(10)
com.Write(strChars)
WScript.Sleep(200)
Loop

objFile.Close
com.Close()

MsgBox("Finished writing to COM")
In order to use the above scripts, copy the code, paste it into a text file and name it with the extension "vbs". Just by double clicking on the file, Windows will invoke wscript.exe, which will then execute the VBscript code.
NB: The above code was formatted by http://formatmysourcecode.blogspot.com/

Saturday, May 16, 2009

Scrolling issue

Mr. BroHogan, of Life Clock and X10 book fame, pointed to a bug in Wide Clock's scrolling. Not exactly sure what, but it looked weird. Took me some time to notice that the left-most character disappears all of a sudden, instead of being scrolled out to the left.
After a long investigation, I found the culprit, a one-liner, in this function:
void setScreenMem(byte sprite1[8], byte sprite2[8], byte sprite3[8], byte sprite4[8])
{
  unsigned long row[16] = {0};
  
  // for each row;
  for (byte i = 0; i < 8; i++)
  {
      byte c1 = sprite1[i] >> 1;
      byte c2 = sprite2[i] >> 1;
      byte c3 = sprite3[i] >> 1;
      byte c4 = sprite4[i] >> 1;
      row[i] = ((((((unsigned long) c1<<5)+c2)<<5)+c3)<<5)+c4;
  }
  
  // scroll 5 times to the left (5 being the max width of a char, as defined);
  for (byte x = 1; x <= 5; x++)
  {
    // for each row;
    for (byte i = 0; i < 8; i++)
    {
      screenMem[i] = row[i] >> (5-x);
    }
    delay(wait);
  }
}
The cast to unsigned long (4 bytes) was missing. Since the default type was int (2 bytes), some of the most significant bits were lost after shifting.
This piece of code

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  shiftLong(31, 0, 17, 12);
  shiftLong(30, 0, 17, 12);
  delay(3000);
}

void shiftLong(byte c1, byte c2, byte c3, byte c4)
{
      unsigned long row = (((((c1<<5)+c2)<<5)+c3)<<5)+c4;
      Serial.print(c1, DEC);
      Serial.print(", ");
      Serial.print(c2, DEC);
      Serial.print(", ");
      Serial.print(c3, DEC);
      Serial.print(", ");
      Serial.print(c4, DEC);
      Serial.print(", ");
      Serial.println(row, BIN);
}
should lead to better understanding. It displays this result (in Arduino IDE 11 and 14, compiled for Diecimila):
31, 0, 17, 12, 11111111111111111000001000101100
30, 0, 17, 12, 1000101100
More to come on the topic of scrolling characters.

Monday, May 11, 2009

Wise Clock version 3, aka "Wide Clock"

The case, bought for a song from a photo shop, was designed for storing 4x6 photo prints. It has a hinged glass door (initially painted black), held in place with little magnets. The nice thing beside the good look is that there is room for expansion (XBee, battery charger, SD card etc).

Watch it in action (video) here.

Saturday, May 9, 2009

Arduino display shield with two 8x8 LED matrices


Apparently, the single 8x8 LED matrix in Wise Clock is not big enough to properly read scrolling messages, so my friends suggested I should make the display bigger.
With minimal changes (hardware and software), I was able to meet their "requirement". So, instead of a bi-color (red/green) matrix, I connected 2 single color (red) matrices to the same shield. Next step was to modify the sketch to use the bigger field.