TideClock
Contents
- 1 Description
- 2 Status
- 3 Features
- 4 License
- 5 Cost
- 6 Hardware design files
- 7 Power
- 8 Console and Debug port
- 9 nfs & tftp
- 10 Cross Compiler
- 11 Booting
- 12 U-Boot
- 13 Busybox
- 14 Building the Linux Kernel
- 15 Root Filesystem (RFS)
- 16 Including RFS in Kernel Image
- 17 I2C and RTC
- 18 GPIO / Hardware Pin I/O
- 19 Links
- 20 USB Info
- 21 Discussion
- 22 Contact
- 23 other Related Projects
Description
Tideclock is an electromechanical clock that displays local tides in bargraph form. The 'bars' are currently implemented as 12 moving pointers on lead-screws approximately 30cm long, but there are many other neat ways one can display a 'bar'. How about columns of water? or a string that is supported at a dozen places?
Being software-controlled, many parameters that are easily altered, such as:
- interval between the 'bars' (presently 1 hour, thus showing the upcoming tides for 12 hours)
- location for which the tides are calculated
- display scaling, or units
One can even display currents instead of tide heights if preferred.
TideClock uses a Linuxstamp by Paul Thomas (see its page here in OpenCircuits) for the processing.
Tide calculations are performed by xtide [[1]] compiled to run on the Linuxstamp.
Motion control and power supply is performed by a custom PCB. The design details are below.
Status
The Software works. A prototype PCB has been assembled and 90% tested. The major remaining tasks are assembling the lead screws and putting the whole thing in a nice wooden cabinet.
Features
- 12 individually-controlled 'bars' for displaying the tide height 12 or 24 hours in the future
- Low power (60 mW between updates; 1.2W when updating the graph)
- configurable Update interval (how often graph is refreshed)
- configurable Scale (meters, feet, fathoms, etc)
- Displays Tide Height or Current Speed
License
All files for this project are licensed under the GNU GPL V2
Cost
The prototypes (4 are in various stages of construction) have cost about $500 each for materials. Labour not included...
Hardware design files
Warning!!! Use this design at your own risk.
Power
Energy is stored by an ~1100 mA-Hr Li-ion cell, which is sufficient for about 30 hours of use when disconnected from external power sources. It is recharged by either 5V from a USB-charger wall-wart, or a solar panel. Average power consumption is approximately 150 mW, so it shouldn't need too large of a panel.
The internal real-time clock (which is how the software knows what time it is, for the calculations) is powered by a 0.47F supercapacitor that charges from the the Li-ion cell. The TideClock should retain its internal time for at least two weeks after discharge of the main battery.
Console and Debug port
A USB connector provides a serial port for console access to the Linux OS. This is used for updating or changing the software, changing the time, or changing other parameters.
nfs & tftp
Cross Compiler
Booting
U-Boot
I left u-boot as-is on the Linuxstamp.
Busybox
Building the Linux Kernel
Download kernel 2.6.33 from kernel.org. Get patch for AT91 from http://maxim.org.za/at91_26.html. Uncompress and apply patch:
cd linux-2.6.33.7 patch -p1 < ../2.6.33-at91.patch
We'll need to have mkimage in the path to create the uImage file, and we'll need the cross-compiler in the path:
export PATH=${PATH}:~/dev/uboot/tools: export PATH=~/x-tools/arm-unknown-linux-gnueabi/bin:${PATH} export CROSS_COMPILE=arm-unknown-linux-gnueabi-
Configure the kernel for compiling with the desired options:
make ARCH=arm ecbat91_defconfig make ARCH=arm menuconfig
In the kernel config menu, turn on/off these features as indicated. Some are optional, some you must do for it to work:
- turn on Kernel Features->"Use the ARM EABI to compile the kernel" (MUST)
- turn off "Kernel .config support"
- turn off Bus Support->"PCCard"
- turn off Kernel Features->"Allow old ABI Binaries to run with this kernel"
- turn off Networking Support->Wireless->"cfg80211 - wirelss configuration API"
- turn off Network Device Support->"Wireless LAN"
- turn off Network Device Support->"PPP support"
- turn on "I2C Core Debugging messages"
- turn on Real Time Clock->"Intersil ISL1208" (MUST if you want to use the external RTC)
- turn on RAMDISK support, so we can put kernel+rfs into flash and run the whole thing out of RAM. During booting the kernel+flash image is uncompressed into RAM and the rfs image mounted as /
- in “Main menu”->“Device Drivers”->“Block devices” make sure “RAM disk support” is selected.
- for the “Default RAM disk size” enter 14000 (this seems OK, in first tests we seemed to need a bit over 7 MB for the rfs.)
- in “Main menu”->“General setup.” select “Initial RAM filesystem and RAM disk (initramfs/initrd) support”
- enter the location of the RFS cpio archive, or RFS path (see below in RFS, read Help section if needed, or check linuxstamp page on OpenCircuits).
Build the kernel; in kernel directory ~/dev/kernel/linux-2.6.33.7:
make ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabi- uImage ... Image arch/arm/boot/uImage is ready
If you entered the location of the RFS cpio archive in the make menuconfig, this uImage will include the RFS, else it will be just the kernel itself and you will need to provide the RFS via NFS or on SD card.
Load the kernel using Linuxstamp's bootloader and minicom's xmodem send option.
Root Filesystem (RFS)
See http://www.opencircuits.com/Linuxstamp and http://processors.wiki.ti.com/index.php/Creating_a_Root_File_System_for_Linux_on_OMAP35x
General steps:
- Made staging dir
- Ran busybox's make install to this staging dir
- Made link in RFS root directory to busybox so kernel launches it
ln -s bin/busybox init
- Created the dev, dev/pts, etc, etc/init.d, lib, mnt, opt, proc, root, sys, tmp, var, and var/log directories.
- Created the device node for the initial console:
sudo mknod dev/console c 5 1
- Created file etc/fstab with following contents:
proc /proc proc defaults 0 0 none /dev/pts devpts mode=0622 0 0
- Created files group, hosts, and passwd in the /etc directory for logging in.
[root@localhost etc]# vi group root:x:0:root [root@localhost etc]# vi passwd root::0:0:root:/root:/bin/dash [root@localhost etc]# vi hosts 127.0.0.1 localhost
- init reads the etc/inittab file to determine what to do at start up, shutdown, or when a user logs in. Created inittab (see sample in refs)
- init runs /etc/init.d/rcS to setup the system. Created rcS (see sample in refs) and made executable by all.
- created etc/mdev.conf
[root@localhost etc]# vi mdev.conf audio 0:5 0666 console 0:5 0600 control.* 0:0 0660 @/bin/mv /dev/$MDEV /dev/snd/ dsp 0:5 0666 event.* 0:0 0600 @/bin/mv /dev/$MDEV /dev/input/ fb 0:5 0666 nfs 0:5 0770 null 0:0 0777 pcm.* 0:0 0660 @/bin/mv /dev/$MDEV /dev/snd/ rtc 0:0 0666 tty 0:5 0660 tty0* 0:5 0660 tty1* 0:5 0660 tty2* 0:5 0660 tty3* 0:5 0660 tty4* 0:5 0660 tty5* 0:5 0660 tty6* 0:5 0660 ttyS* 0:5 0640 urandom 0:0 0444 zero 0:0 0666
- Added in libraries
- Goto the RFS staging area and copy the cross-compiler's libraries into the staging area. Only the *.so libraries are needed. The *.a are used for statically linked programs. Use cp -P to preserve symbolic links, else the RFS gets bloated with actual copies of the libraries. Strip out debug info and unneeded symbols to make the libraries smaller.
cd ~/dev/kernel/rfs sudo cp -rP ~/x-tools/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi/sys-root ./ arm-unknown-linux-gnueabi-strip --strip-unneeded *
- Finally, after you have set up all the libraries you need, run ldconfig to remake /etc/ld.so.cache on the RFS. The cache tells the loader where to find the libraries. You can do this with: (I skipped this step - didn't seem to be a problem (nothing needed the libraries?)
ldconfig -r /mnt
- Make root owner of entire RFS
sudo chown -R root:root ~/dev/kernel/rfs
Including RFS in Kernel Image
See http://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt and also Linuxstamp page on OpenCircuits
The linux kernel source will have the needed scripts and utilities.
.../linux-2.6.33.7/scripts/gen_initramfs_list.sh /path_to_fs_root/ > cpio_list
Make and invoke gen_init_cpio (in .../linux-2.6.33.7/usr)
make gen_init_cpio ../linux-2.6.33.7/usr/gen_init_cpio cpio_list > initramfs.cpio
Gzip the CPIO archive
gzip initramfs.cpio
Copy initramfs.cpio.gz to usr/initramfs_data.cpio.gz, and run the normal kernel make. You will notice that uImage is much larger (size = kernel + fs).
Use Darrell's Bootloader on the Linuxstamp to upload the new kernel+rfs to dataflash. The Linuxstamp should now boot without an SD card and without an NFS server. The u-Boot kernel arguments can still include an nfs server rfs - they will be ignored.
I2C and RTC
The TideClock includes a Real Time Clock (RTC) (Intersil ISL1208) to keep time when the rest of the device is off. The kernel reads the RTC during booting to update the system time, which allows the tidal predictions to be correct for the current time. The RTC is powered by a supercap for several weeks of timekeeping when no other power is available.
Since the Linuxstamp CPU includes its own CPU. it would have been possible to rewire that board to provide a separate backup supply to its crystal but I thought it easier to leave the Linuxstamp unmodified and just provide a separate RTC. It turned out that using the Linuxstamp RTC was no more difficult that the way I chose, so for cost savings one could dispense with the separate RTC.
The ISL1208 communicates via I2C so I had to get that feature operating. As a start, read http://openhardware.wordpress.com/2008/10/13/i2c-fun-with-the-at91rm9200/
I tried
patch -i addRTC.patch -o board-ecbat91.c
but it failed to patch (not right version?) so I made the modifications by hand. A patch file for my mods will be posted shortly...
I also patched the at91rm9200_devices.c file to move the SCK pin from PA26 to PA24, and to slow down the I2C clock from ~167kHz to ~67kHz. A patch file for my mods will be posted shortly...
Remember to also edit the kernel's .config (using make ARCH=arm menuconfig as described in the Kernel section above) to enable the RTC portions of the kernel. Note that rtc0 points to the Linuxstamp's CPU (AT91RM9100) internal RTC, while rtc1 points to the ISL1208.
When testing I2C functionality, you can cross-compile the I2C tools from http://www.lm-sensors.org/wiki/I2CTools and they will run on the Linuxstamp. With the ISL1208 attached to pins 24 (I2C_SCK) and 25 (I2C_SDA), it appears on I2C bus 0 at address 0x6f (0b1101111x) and you can read back the minutes by:
./i2cget 0 0x6f 0x01
When an ISL1208 is powered up for the first time or following total power loss (i.e. no backup battery), its time registers will not begin updating until at least one of time registers has been written to. To write to the registers the write-enable bit 4 of register 0x07 needs to be set to 1 first. e.g. To set the time to 23 minutes after the hour, do:
./i2cset 0 0x6f 0x07 0x10 ./i2cset 0 0x6f 0x01 23
The I2C tools won't access the clock when a kernel that has control of rtc1 is running. Use the busybox hwclock ... function instead. On the command line, set the system time/date and then write the system time to the ISL1208 by:
date -s "2011-12-29 11:40" busybox hwclock -w -f /dev/rtc1
Reading the RTC is similar:
busybox hwclock -f /dev/rtc1 rtc-isl1208 0-006f: read time OK Thu Dec 29 11:25:34 2011 0.000000 seconds
TODO: the ISL1208 can be tuned (calibrated) to minimize inaccuracies.
See also the kernel's ./Documentation/rtc.txt, which includes a test program for messing with the RTC. The sysfs interface under /sys/class/rtc/rtcN provides read-only access to various rtc attributes. Google for more info.
Note that the CPU's internal RTC (rtc0) is *not* updated automatically from either the ISL1208 or the system clock. If you plan on using it and want it synced with the rtc1/system time, the toss the following into /etc/init.d/rcS.
busybox hwclock -w -f /dev/rtc0
GPIO / Hardware Pin I/O
Links
I won't repeat the ones listed on the OpenCircuits pages for the Linuxstamp and Linuxstamp II 9260.
USB Info
Discussion
You could try the <Discussion> button at the top of this page, or contact me at the address below:
Contact
For questions or comments please contact Bjarne (bjarneh /at/ shaw /dot/ ca)