Monday, October 20, 2014

cloudClock: ntpstat

In order to find out the status of the ntp daemon, there seem to be 2 possibilities: ntpq or ntpstat.
ntpq is by far the one that gives more info, really too much for my liking, I just want to find out if the clock is in sync or not!! so I went for ntpstat. As I mentioned in my previous post, there is no ntpstat in linino, so I had to compile it from scratch. This was easy. I got the ntpstat source code from here and compiled it doing:

../linino/trunk/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-gcc ntpstat.c -o ntpstat

Monday, October 13, 2014

cloudClock: time keeping

Part of the beauty of the cloudClock is the fact that it does not require having to set the time. For that I will use ntpd to keep linino on time. Turns out that linino already has ntpd running:

/usr/sbin/ntpd -n -p 0.openwrt.pool.ntp.org -p 1.openwrt.pool.ntp.org -p 2.openwrt.pool.ntp.org -p 3.open

First thing I thought was that I would like to change the ntp servers being used and select some servers near by. I also wanted to the change the timezone to my current timezone. Turns out both those things are configured in the same file: /etc/config/system

Original file was:

config system
option hostname 'Arduino'
option timezone 'UTC'
option timezone_desc 'Rest of the World (UTC)'

config timeserver 'ntp'
list server '0.openwrt.pool.ntp.org'
list server '1.openwrt.pool.ntp.org'
list server '2.openwrt.pool.ntp.org'
list server '3.openwrt.pool.ntp.org'
option enable_server '0'

And my modified file is now:

config system
option hostname 'Arduino'
option timezone 'CET-1CEST,M3.5.0,M10.5.0/3'
option timezone_desc 'Europe/Madrid'

config timeserver 'ntp'
list server '0.pool.ntp.org'
list server '1.pool.ntp.org'
list server '2.pool.ntp.org'
list server '3.pool.ntp.org'
option enable_server '0'

I got the timezone to set from this list: http://wiki.openwrt.org/doc/uci/system#time.zones

I need a way to find out if ntpd is working correctly. There seems to be 2 possibilities: ntpstat and ntpq, but I could not find ntpstat in linino, so tried with ntpq. Unfortunately ntpq was not working either. My conclusion was that it was using busybox ntpd, rather than a fully featured ntpd, so I installed ntpd doing:

opkg update
opkg install ntpd
/etc/init.d/sysntpd disable
/etc/init.d/ntpd enable
/etc/init.d/ntpd start

Now ntpq works!!! just need to figure out how do I parse the output of ntpq to get something meaningful.

On the arduino side, I bought an RTC chip module to make sure the clock is on time, even when there is no internet connection. I will get back to that whenever the RTC module arrives.


Saturday, October 11, 2014

cloudClock: getting flite to work in Arduino Yun

In my last entry I installed flite from opkg and when I tried to run it with a simple "flite -t hello" all I got was a Segmentation Fault, so next step was to fix that.

First thing was find out what was causing it to seg. fault, strace to the rescue. For newbies: strace is a linux tool for tracing system calls and signals... a must know for a linux developer. Strace was not included in linino by dafault, so "opkg install strace". Once installed I did: "strace flite" and got the following:

strace flite
execve("/usr/bin/flite", ["flite"], [/* 11 vars */]) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x77435000
stat("/etc/ld.so.cache", 0x7fce6bf0)    = -1 ENOENT (No such file or directory)
open("/lib/libflite_cmu_us_kal16.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libflite_cmu_us_kal16.so.1", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=3705608, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x77434000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0007\360\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 3772416, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x77087000
old_mmap(0x77087000, 3693236, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x77087000
old_mmap(0x7741c000, 15112, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x385000) = 0x7741c000
close(3)                                = 0
munmap(0x77434000, 4096)                = 0
open("/lib/libflite_usenglish.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libflite_usenglish.so.1", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=88944, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x77434000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0b\320\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 155648, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x77061000
old_mmap(0x77061000, 68232, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x77061000
old_mmap(0x77082000, 19312, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x11000) = 0x77082000
close(3)                                = 0
munmap(0x77434000, 4096)                = 0
open("/lib/libflite_cmulex.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libflite_cmulex.so.1", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=597680, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x77434000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0!\360\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 663552, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76fbf000
old_mmap(0x76fbf000, 590444, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x76fbf000
old_mmap(0x77060000, 3760, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x91000) = 0x77060000
close(3)                                = 0
munmap(0x77434000, 4096)                = 0
open("/lib/libm.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=85356, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x77434000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\26\200\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 151552, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76f9a000
old_mmap(0x76f9a000, 84896, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x76f9a000
old_mmap(0x76fbe000, 3436, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x14000) = 0x76fbe000
close(3)                                = 0
munmap(0x77434000, 4096)                = 0
open("/lib/libflite.so.1", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/usr/lib/libflite.so.1", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=125740, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x77434000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\\ \0\0\0004"..., 4096) = 4096
old_mmap(NULL, 192512, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76f6b000
old_mmap(0x76f6b000, 121476, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x76f6b000
old_mmap(0x76f99000, 2860, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x1e000) = 0x76f99000
close(3)                                = 0
munmap(0x77434000, 4096)                = 0
open("/lib/libgcc_s.so.1", O_RDONLY)    = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=77080, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x77434000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0006\320\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 143360, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76f48000
old_mmap(0x76f48000, 76672, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x76f48000
old_mmap(0x76f6a000, 3352, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x12000) = 0x76f6a000
close(3)                                = 0
munmap(0x77434000, 4096)                = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=359599, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x77434000
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\10\0\0\0\1\0\0\237\320\0\0\0004"..., 4096) = 4096
old_mmap(NULL, 446464, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76edb000
old_mmap(0x76edb000, 352964, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x76edb000
old_mmap(0x76f41000, 7343, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x56000) = 0x76f41000
old_mmap(0x76f43000, 17508, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x76f43000
close(3)                                = 0
munmap(0x77434000, 4096)                = 0
open("/lib/libflite_cmulex.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libflite_cmulex.so.1", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=597680, ...}) = 0
close(3)                                = 0
open("/lib/libflite_usenglish.so.1", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/libflite_usenglish.so.1", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=88944, ...}) = 0
close(3)                                = 0
open("/lib/libgcc_s.so.1", O_RDONLY)    = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=77080, ...}) = 0
close(3)                                = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=359599, ...}) = 0
close(3)                                = 0
open("/lib/libflite.so.1", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/usr/lib/libflite.so.1", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=125740, ...}) = 0
close(3)                                = 0
open("/lib/libgcc_s.so.1", O_RDONLY)    = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=77080, ...}) = 0
close(3)                                = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=359599, ...}) = 0
close(3)                                = 0
open("/lib/libflite.so.1", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/usr/lib/libflite.so.1", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=125740, ...}) = 0
close(3)                                = 0
open("/lib/libgcc_s.so.1", O_RDONLY)    = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=77080, ...}) = 0
close(3)                                = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=359599, ...}) = 0
close(3)                                = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=359599, ...}) = 0
close(3)                                = 0
open("/lib/libm.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=85356, ...}) = 0
close(3)                                = 0
open("/lib/libgcc_s.so.1", O_RDONLY)    = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=77080, ...}) = 0
close(3)                                = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=359599, ...}) = 0
close(3)                                = 0
open("/lib/libc.so.0", O_RDONLY)        = 3
fstat(3, {st_mode=S_IFREG|0755, st_size=359599, ...}) = 0
close(3)                                = 0
stat("/lib/ld-uClibc.so.0", {st_mode=S_IFREG|0755, st_size=28968, ...}) = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|0x4000000, -1, 0) = 0x77434000
set_thread_area(0x7743b750)             = 0
mprotect(0x76f41000, 4096, PROT_READ)   = 0
mprotect(0x77436000, 4096, PROT_READ)   = 0
ioctl(0, TIOCNXCL, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TIOCNXCL, {B38400 opost isig icanon echo ...}) = 0
brk(0)                                  = 0x9f2000
brk(0x9f3000)                           = 0x9f3000
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0xf0000} ---
+++ killed by SIGSEGV +++
Segmentation fault

From the highlighted text, you can see that it did not find any of the shared libraries that flite needs. A search for those libraries showed that they were on a different folder from where flite was searching. They were in /usr/lib as opposed to /lib:

root@Arduino:~# find / -name *flite*
/overlay/usr/bin/flite
/overlay/usr/lib/libflite_cmu_time_awb.so.1.3
/overlay/usr/lib/libflite_usenglish.so.1.3
/overlay/usr/lib/opkg/info/flite.control
/overlay/usr/lib/opkg/info/flite.list
/overlay/usr/lib/libflite_cmu_time_awb.so.1
/overlay/usr/lib/libflite_cmulex.so.1.3
/overlay/usr/lib/libflite_cmu_us_kal16.so.1.3
/overlay/usr/lib/libflite_usenglish.so.1
/overlay/usr/lib/libflite.so.1
/overlay/usr/lib/libflite_cmu_us_kal.so.1.3
/overlay/usr/lib/libflite_cmu_us_kal.so.1
/overlay/usr/lib/libflite.so.1.3
/overlay/usr/lib/libflite_cmulex.so.1
/overlay/usr/lib/libflite_cmu_us_kal16.so.1
/usr/bin/flite
/usr/lib/opkg/info/flite.control
/usr/lib/opkg/info/flite.list
/usr/lib/libflite_cmu_time_awb.so.1.3
/usr/lib/libflite_usenglish.so.1.3
/usr/lib/libflite_cmu_time_awb.so.1
/usr/lib/libflite_cmulex.so.1.3
/usr/lib/libflite_cmu_us_kal16.so.1.3
/usr/lib/libflite_usenglish.so.1
/usr/lib/libflite.so.1
/usr/lib/libflite_cmu_us_kal.so.1.3
/usr/lib/libflite_cmu_us_kal.so.1
/usr/lib/libflite.so.1.3
/usr/lib/libflite_cmulex.so.1
/usr/lib/libflite_cmu_us_kal16.so.1

I just copied them across to /lib, but that did not work. Strace did no longer complain about the libraries not being found, but seg. fault was still there. From here I figured out other people had gone through the same issue in openWRT and fixed it by compiling 1.4 instead of 1.3. They were so kind there to also share the new makefile, which did not quite fit, but it was a good starting point. So I replaced the Makefile for flite in my linino tree (you may want to see this again for how to compile packages for linino) in linino/trunk/feeds/packages/sound/flite with this one:

#
# Copyright (C) 2006-2010 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
include $(TOPDIR)/rules.mk

PKG_NAME:=flite
PKG_VERSION:=1.4-release
PKG_RELEASE:=1

PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=http://www.speech.cs.cmu.edu/flite/packed/flite-1.4/
PKG_MD5SUM:=b7c3523b3bbc6f29ce61e6650cd9a428
PKG_CAT=bzcat

PKG_BUILD_PARALLEL:=1
PKG_INSTALL:=1

include $(INCLUDE_DIR)/package.mk

define Package/flite
  SECTION:=sound
  CATEGORY:=Sound
  DEPENDS:=@!GCC_VERSION_3_4_6
  TITLE:=Text-to-speech for embedded systems
  URL:=http://www.speech.cs.cmu.edu/flite/index.html
endef

define Package/flite/description
Festival Lite is a stripped down version of Festival,
    the well-developed text-to-speech program written in C++.
    This program is written in C to keep memory usage low.
endef

TARGET_LDFLAGS += -lm

define Build/Configure
$(call Build/Configure/Default, \
--enable-shared \
--with-audio="oss" \
--with-vox="cmu_us_kal16" \
--prefix="$(PKG_INSTALL_DIR)/usr" \
--exec-prefix="$(PKG_INSTALL_DIR)/usr" \
--bindir="$(PKG_INSTALL_DIR)/usr/bin" \
)
endef

define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include/flite
$(CP) $(PKG_INSTALL_DIR)/usr/include/flite/{cst,flite}*.h $(1)/usr/include/flite/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libflite*.so.* $(1)/usr/lib/
endef

define Package/flite/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/flite $(1)/usr/bin/
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libflite*.so.* $(1)/usr/lib/
endef

$(eval $(call BuildPackage,flite))

I also remove the patches folder and compiled flite 1.4 by doing "make package/flite/compile V=s" in /linino/trunk. After that I removed the previously installed flite in linino by doing "opkg remove flite" and copied the result of my compilation by doing:

rsync -avz -e ssh linino/trunk/build_dir/target-mips_r2_uClibc-0.9.33.2/flite-1.4-release/ipkg-install/usr root@192.168.0.9:/

Running then "flite -t hello" resulted in my arduino saying hello. Unfortunately, randoms attempts of running the same line ended up on the board throwing an error message instead of talking. The error is the following:

flite -t hello
VAL: tried to access car in 119 typed val

Getting there, but not quite there yet...

In the same place where I got the suggestion of using version 1.4, they suggest running it many times until it succeeds. I am using this script (based on the one they had):

REP=1
until [ "$REP" -eq 0 ]
do
flite -voice kal16 -t  "$1"
REP="$?"
done

The birth of a new project: CloudClock

So my alarm clock broke recently. Actually it was only the powersupply. What a great excuse for new project with my arduino yun!!

Since I built my grooveshark radio, my yun has been unused, I do not find time to listen to music at home these days, so the grooveshark radio was not of much use, so my broken alarm was a good excuse to put the yun back on business.

My plan is the following:
1. No screen: The thing should talk
2. Just one button: All the control should be via web
3. Should be reliable: I want it to be a real replacement for my broken alarm, so I want it to be reliable as a commercial device... or more.

For 1 and 2, I might end up cheating and using the 16x2 screen and the rotary encoder... who knows...

So my first step was getting the yun to talk. For that I decided to use festival lite (or flite). So... ssh into linino, opkg update, opkg install flite:
good news: the package was there
bad news: it did not fit in the available memory

So I had to extend my linino memory and for that I could use the SD card port. Knowing that someone else would have probably done this already, did a google search and voila: Expanding Yun Disk Space

Worked...

Boot again, ssh into linino, opkg update, opkg install flite... now it fitted!!!

next step was to give it a try: flite -t hello
Segmentation Fault

Back to the begining... now need to figure out why it does not work...