Start android AOSP – CyanogenMod development : the firsts steps

I’m still waiting for my 9$ Arduino…some mistake in Hong Kong customs procedure has generated a huge delay in shipment.

But finally I found an “idea” for some Cyanogen development, and I want to share here the steps that I’m doing.

The Goal

At work I’m working on a feature that requires frequent “Force stop” and “Clear data” during the debug and development phase. I want to improve the “Application info” popup menu on the notification area (long click on the app notification) in order to add two new item: “Force Stop” and “Clear data”.

The Player

    • At the moment the Nexus S is not available, so I will use the ugliest android phone ever seen: the Motorola Defy (MB 526), aka “Jordan” – specs (From GSM arena)

image

    • I will use the CyanogenMod fork by Quarx2k, based on Android JB 4.1.2 – XDA forum post
    • My old development machine @ work – a Dell studio XPS with Ubuntu 12.04 LTS

image

Step 0 : setup the development environment

Simply follow the post on XDA forum. After a few hours you should have your standard build from JB sources

Step 1 : setup a new github repo

I need to modify the “frameworks/base” project, because the notification area sources are in “frameworks/base/packages/SystemUI” folder.  Simply go to “https://github.com/Quarx2k/android_frameworks_base” and fork this repository. My forked repo location is “https://github.com/sarbyn/android_frameworks_base_jordan

Now you need to add a “local_manifest.xml” in your .repo/local_manifests folder, in which you must define the new repository:

<?xml version="1.0" encoding="UTF-8"?>
   <manifest>
   <remove-project name="Quarx2k/android_frameworks/base"/>
   <project remote="github" path="frameworks/base" name="sarbyn/android_frameworks_base_jordan" revision="jellybean"/>
</manifest>

A simple explanation (from CM wiki)

  • remote — the name of the remote. this can be one that was defined in either the regular manifest or local_manifest.xml.
  • name — the name of the git project– for github it has the format account_name/project_name.
  • path — where the git repository should go in your local copy of the source code.
  • revision — (OPTIONAL) which branch or tag to use in the repository.

Now you are ready to “repo sync” your source tree.

Step 2 : start editing

Before you change anything you need to start a new git branch. Go into the main project folder and do a “repo start banchname frameworks/base“. Now you are ready to modify the code in a new git branch.

Step 3 : build

When all the development is done, do a full build with the standard procedure

source build/envsetup.sh && brunch mb526
make -j# bacon

# represents double the cores you have on your computer

Step 4 : commit and push on github repo

Enter in frameworks/base and check the repo status with git status. Add all the modified files with the standard git add FILENAME and commit the changes with git commit -m ‘message’. Now you are ready to upload the new git branch on server git push -u github branch_name

Step 5 : backup & install

The last step is very simple: go into recovery mode and do a full Nandroid backup. After that you can flash your build and try if it works 🙂

EUREKA!
EUREKA!

Thermistor sample code for Arduino – Raspberry

This is a C++ class for a simple NTC thermistor. I used the thermistor included in the cooking-hacks.com starter kit (datasheet) and the cooking-hacks.com Raspebby to Arduino shield, but this sample is easily adaptable for any NTC thermistor or also for Arduino platform. It can be used with another NTC thermistor: simply change the BasicThermistor.h values:

  • BETA (o B-Value) : the beta value of thermistor
  • THERMISTOR: zero power resistance at 25° C
BasicThermistor schema
BasicThermistor schema

Some notes:

  • This class is designed for a read every 10 seconds.
  • Check the real value of 10k resistance with a multimeter! The 10% tollerance changes the value of about ± 1° C!. In my example I use 9840 Ω instead of 10000 Ω
  • I use a arithmetic mean over 12 readings (2 minutes) in order to normalize the temperature value and discard read errors
  • I use a simple “is_valid_value” function that discard a macroscopic read error. A “digital” read error of ± 20 is converted to an error of ± 14° C ! So if the previous valueis too big or too small, discard the current value

Header file – BasicThermistor.h

/*
 * BasicThermistor.h
 *
 * Created on: 07/ago/2013
 * Author: sarbyn
 * Website: http://www.sarbyn.com
 */
#ifndef BASICTHERMISTOR_H_
#define BASICTHERMISTOR_H_

#include &quot;arduPi.h&quot;
#include

/**
 * Based on cooking-hacks NTC thermistor - datasheet available at
 * http://www.cooking-hacks.com/skin/frontend/default/cooking/pdf/159-282-86001.pdf
 */

// The real 10k resistor value
#define TENKRESISTOR 9840.0f
// Thermistor beta value (from datasheet)
#define BETA 3950.0f
// The thermistor value at room temp (25 C)
// the original value was 2800 ohm
#define THERMISTOR 2700.0f
// The room temperature (25 C) in kelvin
#define ROOMTEMPK 298.15f

// Number of readings over which calculate
// the temperature
#define READINGS 12
// Delay (in ms) between Wire operations
#define DELAY_BETWEEN_OPERATION 20

// The digital value readed from ADC
// must be lower than DIGITAL_TOLLERANCE
// Otherwise it is treaded as a read error
#define DIGITAL_TOLLERANCE 20
// If the digital value readed from ADC is wrong for
// more than DIGITAL_TOLLERANCE_COUNTER, it is a correct value
// and so use it. This is used in case of sudden
// temperature change. If the temperature changes suddenly,
// the value is discarded for DIGITAL_TOLLERANCE_COUNTER reads. After that
// the value is accepted
#define DIGITAL_TOLLERANCE_COUNTER 6

#define ADC_I2C_ADDRESS 8

class BasicThermistor {
public:
   BasicThermistor(byte i2c_address, boolean debug_flag);
   float read_temperature();
private:
   byte address;
   boolean debug;
   int digital_value;
   float read_buffer[READINGS];
   unsigned int cached_digital_value;
   float temperature;
   int invalid_read_counter;
   int buffer_pointer;

   int read_digital_value();
   int is_valid_value(int value);
   float calc_temperature(int value);
};

#endif /* BASICTHERMISTOR_H_ */

Class file – BasicThermistor.cpp

/*
 * BasicThermistor.cpp
 *
 * Created on: 07/ago/2013
 * Author: sarbyn
 * Website: http://www.sarbyn.com
 *
 */

/**
 * Based on cooking-hacks NTC thermistor - datasheet available at
 * http://www.cooking-hacks.com/skin/frontend/default/cooking/pdf/159-282-86001.pdf
 */

#include &quot;BasicThermistor.h&quot;

// Costructor
BasicThermistor::BasicThermistor(byte i2c_address, boolean debug_flag) {
  address = i2c_address;
  debug = debug_flag;
  temperature = 0.0;
  cached_digital_value = 0;
  digital_value = 0;
  invalid_read_counter = 0;
  buffer_pointer = 0;

  for (int i = 0; i &lt; READINGS; i++) {
    read_buffer[i] = -1.0f;
  }
}
// Read the digital value from ADC using Wire class
int BasicThermistor::read_digital_value() {
  unsigned char val_0 = 0;
  unsigned char val_1 = 0;
  unsigned int digital_value;
  Wire.beginTransmission(ADC_I2C_ADDRESS);
  Wire.write(address);
  // sleep in order to reduce read error
  delay(DELAY_BETWEEN_OPERATION);
  Wire.requestFrom(ADC_I2C_ADDRESS, 2);
  // sleep in order to reduce read error
  delay(DELAY_BETWEEN_OPERATION);
  val_0 = Wire.read();
  // sleep in order to reduce read error
  delay(DELAY_BETWEEN_OPERATION);
  val_1 = Wire.read();
  // sleep in order to reduce read error
  delay(DELAY_BETWEEN_OPERATION);
  digital_value = int(val_0)*16 + int(val_1&gt;&gt;4);

  if (debug) {
    printf(&quot;[BT] val [%2x,%2x]\n&quot;, val_0, val_1);
    printf(&quot;[BT] Read digital value %d\n&quot;, digital_value);
  }
  return digital_value;
}

// Check if the readed value is valid
int BasicThermistor::is_valid_value(int value) {
  if (cached_digital_value == 0) {
    cached_digital_value = value;
    return 1;
  }

  // check against DIGITAL_TOLLERANCE
  if (abs(cached_digital_value - value) &lt; DIGITAL_TOLLERANCE) {
    if (debug) printf(&quot;[BT] Valid digital value %d\n&quot;, value);
    cached_digital_value = value;
    invalid_read_counter = 0;
    return 1;
  }
  if (invalid_read_counter &gt; DIGITAL_TOLLERANCE_COUNTER) {
    // too many invalid readings ---&gt; this is a valid read
   if (debug) printf(&quot;[BT] Too many invalid digital value %d..so use it\n&quot;, value);
   cached_digital_value = value;
   invalid_read_counter = 0;
   return 1;
 }

  // throw away invalid reading
  invalid_read_counter++;
  if (debug) printf(&quot;[BT] Invalid digital value %d\n&quot;, value);
  return 0;
}

// Convert the ADC value to Celsius Temperature
float BasicThermistor::calc_temperature(int value) {
  // convert value
  float analog_value = value * 1023.0 / 4095.0;

  analog_value = (1023 / analog_value) - 1;
  analog_value = TENKRESISTOR / analog_value;
  analog_value = analog_value / THERMISTOR;

  if (debug) printf(&quot;[BT] Analog value %f\n&quot;, analog_value);

  float kelvin = log(analog_value);
  kelvin /= BETA;
  kelvin += 1.0 / ROOMTEMPK;
  kelvin = 1.0 / kelvin;

  return kelvin - 273.15;
}

// Main read function: read the current temperature and return it.
// This is designed for a read every 10 seconds: it collects 12 readings
// (READINGS macro value, 2 minutes) and calculate mean over all the values.
// In this way the temperature value does not change suddenly and
// become more stable
float BasicThermistor::read_temperature() {
  digital_value = read_digital_value();
  float single_temperature;
  if (is_valid_value(digital_value)) {
    single_temperature = calc_temperature(digital_value);
    if (debug) printf(&quot;[BT] Single current temperature is %f\n&quot;, single_temperature);
  } else {
    single_temperature = calc_temperature(cached_digital_value);
    if (debug) printf(&quot;[BT] Invalid temp, using cached value %f\n&quot;, single_temperature);
  }

  if (debug)
    printf(&quot;[BT] Storing the temp at pointer %d\n&quot;, buffer_pointer);

  read_buffer[buffer_pointer] = single_temperature;
  buffer_pointer++;

  if (read_buffer[buffer_pointer] == -1.0f) {
    // this is the first reading....init the buffer
    for (int i = buffer_pointer; i &lt; READINGS; i++) {
      read_buffer[i] = single_temperature;
    }
  }

  // reset the pointer
  if (buffer_pointer == READINGS) buffer_pointer = 0;

  temperature = 0;

  if (debug) {
    printf(&quot;[BT] Temp. buffer[&quot;);
    for (int i = 0; i &lt; READINGS; i++) {
      printf(&quot;%0.1f,&quot;, read_buffer[i]);
    }
    printf(&quot;]\n&quot;);
  }

  for (int i = 0; i &lt; READINGS; i++) {
    temperature += read_buffer[i];
  }

  temperature /= READINGS;

  return temperature;
}

A $9 arduino board

Some days ago I found on indiegogo.com this campaign:

$9 ARDUINO Compatible STARTER KIT

The goal of the founder is to reach 12.000$ and start the production of the Arduino-like board, and now the campain is over 73.000$! . With 12$ (9$ + shipping), or about 9€, you can start to play with Arduino and electronics. I’ve never tried Arduino boards and yesterday I decided to bought one starter kit from indiegogo.com, so in September my little Raspberry Pi will have a new little friend 🙂

LiquidCrystal_i2c for ArduPi

I bought on ebay a simple LCD screen with an i2c controller. My purpose is to add a simple output screen to my project TermoPi (a smart thermostat for my home). I found a ready-to-use CPP library called LiquidCrystal_I2C that helps the developer to connect the LCD screen to an Arduino board. I want to use my raspberry Pi with the coocking-hacks.com “Raspberry to arduino shields” , a connection board that export the arduino input-output pins, using the arduino conventions. A developer can use the Arduino coding style and libraries with his RaspberryPi, using ArduPi CPP library and coocking-hacks shield. But the original LiquidCrystal_I2C library is not compatible with ArduPi compatibility library: this library is similiar to arduino SDK…but it’s not arduino SDK:

  • LiquidCrystal_I2C refers to Arduino “print.cpp” functions, not available on ArduPI
  • ArduPi Wire CPP class implements a different Wire.endTrasmission() function, that close and release the I2C comunication pins (it seems a bug)

After some little changes, LiquidCrystal_I2C is ready to use on RaspberryPi with ArduPI library. You can download the library sources from my Bitbuchet GitHub repository:

https://github.com/sarbyn/liquidcrystal_i2c-for-ardupi