A year and a half ago I got strange obsessive idea to make a “computational cluster” out of old tablets.
I actually wanted to replace my ASUS EB1505 nettop, which works as my home server, with a bunch of tablets running Linux.
I imagined how I designate separate roles to each tablet, make different firewall rules for each of them.
How I have a swarm of small independent devices and low power consumption at the same time…
How each device has it’s own UPS, LCD display…
All these dreams have failed 🙂 Failed in many ways if not in all of possible ways…
But it was fun nevertheless. I had never built a linux kernel from source before. Had never built u-boot let along tamper with it.
The active phase of learning, designing and constructing lasted for about four months.
After that for a few months I tested these systems and tried to make them reliable.
I failed.
Eventually I accepted that I can’t make a usable server on a tablet hardware.
At least if these tablets are Ainol Novo7 Aurora and Ainol Aurora 2 i.e. tablets, based on Allwinner A10 and AMLogic AML8726-MX SoC.
My observations lead me to the conclusion that these devices may have an incredible uptime of 2-3 years if you do not connect external hard drive to them and if they basically do nothing.
Eventually I found a task that is suitable for them and especially for their very good 7 inch IPS LCD screens.
I began to use them as a clock.
Perhaps, if I knew that it is impossible (for me) to do a server of these tablets I would make this clock as an Android App.
It would have graphical interface etc.
But the chain of events lead me to the clock, made as a linux console application.
But wait… This is a separate topic.
I just want to say, that I have an ARM tablet with 7-inch IPS screen, running Linux without GUI and I decided to use it as a clock.
I get time from NTP servers, I get outside temperature from openweathermap and I get inside temperature and humidity from HTU21 sensor, attached to I2C bus of the tablet.
I was lucky and two of my tablets have additional, unsoldered pads on the motherboard with I2C bus so I could connect my HTU21 relatively easily.
After ten minutes of swearing and cursing, which accompanied my attempts to solder two wires to 0.5mm pads with 0.25mm gaps between them, I would love to just have a simple script to check that my HTU21 is responding.
It was especially desirable for AML8726-MX SoC which has vendor-provided lopsided old kernel with unusual response to i2c scan.
I searched for such a script but couldn’t find one. Perhaps there are some, written in Python, but I’m not familiar with this language and its means of module installation.
So I wrote a Perl script which is based on i2c-tools package, It also uses Time::HiRes module to get delays less than 1 sec.
The algorithm I use is mimicked from the HTU21 Arduino library by Daniel Wiese.
Here it is:
Perl script
#! /usr/bin/perl use strict; use utf8; use Time::HiRes qw(usleep); my $HTU_I2C_ADDR = 0x40; my $HTU_I2C_BUS = 1; my $TRIGGER_TEMP_MEAS_NH = 0xF3; my $TRIGGER_HUM_MEAS_NH = 0xF5; my $TRIGGER_READ_USER_REG = 0xE7; my $SOFT_RESET = 0xFE; my $HTU_T = 0; my $HTU_RH = 0; `i2cset -y $HTU_I2C_BUS $HTU_I2C_ADDR $SOFT_RESET`; usleep(15000); `i2cset -y $HTU_I2C_BUS $HTU_I2C_ADDR $TRIGGER_READ_USER_REG`; usleep(5000); my $r = `i2cget -y $HTU_I2C_BUS $HTU_I2C_ADDR`; # read user reg (print "Got response $r instead of 0x02 after Soft Reset. Terminating.\n"), exit 0 if $r != '0x02'; print "Soft Reset OK\n"; usleep(50000); while (1){ if(HTUmeasure()){ print $HTU_T, " C ", $HTU_RH, " % \n"; }else{ print "HTU error\n"; } sleep 5; } sub HTUgetT{ my @data = (0,0,0); `i2cset -y $HTU_I2C_BUS $HTU_I2C_ADDR $TRIGGER_TEMP_MEAS_NH`; # measure temperature usleep(100000); my $resp = `i2ctransfer -y $HTU_I2C_BUS r3\@$HTU_I2C_ADDR`; # read three bytes i2ctransfer -y 1 r3@0x40 @data = split(/\s+/,$resp); return 0 if not checkCRC8(@data); my $St = (($data[0] << 8) | ($data[1] & 0xFC)) % 65536; $HTU_T = -46.85 + 175.72 * $St / 65536.0; return 1; } sub HTUgetRH{ my @data = (0,0,0); `i2cset -y $HTU_I2C_BUS $HTU_I2C_ADDR $TRIGGER_HUM_MEAS_NH`; # measure humidity usleep(20000); my $resp = `i2ctransfer -y $HTU_I2C_BUS r3\@$HTU_I2C_ADDR`; #read three bytes i2ctransfer -y 1 r3@0x40 @data = split(/\s+/,$resp); return 0 if not checkCRC8(@data); my $Srh = (($data[0] << 8) | ($data[1] & 0xFC)) % 65536; $HTU_RH = -6.0 + 125.0 * $Srh / 65536.0; $HTU_RH += (25.0 - $HTU_T) * (-0.15); # temperature compensation $HTU_RH = 0.0 if $HTU_RH < 0; $HTU_RH = 100.0 if $HTU_RH > 100; return 1; } sub HTUmeasure{ $HTU_T = "--"; $HTU_RH = "--"; return 0 if(!HTUgetT()); return 0 if(!HTUgetRH()); return 1; } sub checkCRC8{ my $in_crc = pop(@_); my $crc = 0; for(my $i = 0; $i < 2; $i++) { $crc = $crc ^ $_[$i]; for(my $b = 7; $b >= 0; $b--) { if($crc & 0x80){ $crc = (($crc << 1) ^ 0x31 ) ;} else {$crc = ($crc << 1)} $crc = $crc % 256; } } return $crc == $in_crc; } |
Just a few notes here.
1) If something goes wrong during the communication you will see an error messages from i2c-tools on your STDERR output.
2) Personally I was able to detect my HTU21 device using i2cdetect, but it was impossible to communicate with it until I removed some touchscreen driver from the kernel config and recompiled the kernel. This driver anticipated to have its IC on the same 0x40 I2C address.
3) I saw a mention on the internet that HTU21 driver is present in the Linux kernel since 4.4 (CONFIG_HTU21). The project on the photo above is running a vendor-provided kernel 3.10.x so I think there is no HTU21 driver there, but I think I will check the kernel module for my other tablets which run recent kernel versions.