# Automatic Magnetometer Calibration With Arduino

If we take readings from a 3-axis magnetometers like HMC5883L, AK8963C (used in MPU9250) or LSM303DLHC and plot them, its response should be a sphere with ceter at origin.

In practice, due to the presence of hard and soft iron distortions, the response will be an ellipsiod with its center shifted away from origin. We need to calibrate the magnetometer to nullify the distortions.

First we need to get sample readings of magnetometer in various positions. Depending on the magnetometer, we need to connect it to arduino and take readings by rotating it in 8 shape.

#### Calibration

Hard iron biases shifts center away from origin. We can eliminate this error by calculating the offsets and shifting the readings.

```int mx, my, mz;

int mx_min, my_min, mz_min;
int mx_max, my_max, mz_max;
int mx_offset, my_offset, mz_offset;

int mx_calibrated, my_calibrated, mz_calibrated;

// get min/max values by taking readings
// from magnetometer of your choice

mx_offset = (mx_min + mx_max)/2;
my_offset = (my_min + my_max)/2;
mz_offset = (mz_min + mz_max)/2;

mx_calibrated = mx - mx_offset;
my_calibrated = my - my_offset;
mz_calibrated = mz - mz_offset;
```

Soft iron biases makes the axial responses uneven which results in ellipsiod shape. An easier way to correct this is to rescale the axial readings to an average value.

```int mx_scale, my_scale, mz_scale;

mx_scale = (mx_max - mx_min)/2;
my_scale = (my_max - my_min)/2;
mz_scale = (mz_max - mz_min)/2;

float avg_scale = (mx_scale + my_scale + mz_scale)/3;

mx_calibrated = avg_scale/(mx - mx_offset);
my_calibrated = avg_scale/(my - my_offset);
mz_calibrated = avg_scale/(mz - mz_offset);
```

We can caclulate these biases once and store them in our code so that we don't need to calibrate it everytime. We can also write an auto update function which will recalibrate offsets & scale for every new reading.

# Django Tips & Tricks #9 - Auto Register Models In Admin

Inbuilt admin interface is one the most powerful & popular feature of Django. Once we create the models, we need to register them with admin, so that it can read metadata and populate interface for it.

If the django project has too many models or if it has a legacy database, then adding all those models to admin becomes a tedious task. To automate this process, we can programatically fetch all the models in the project and register them with admin.

```from django.apps import apps

models = apps.get_models()

for model in models:
```

This works well if we are just auto registering all the models. However if we try some customisations and try to register them in `admin.py` files in our apps, there will be conflicts as Django doesn't allow registering the same model twice.

So, we need to make sure this piece of code runs after all `admin.py` files are loaded and it should ignore models which are already registered. We can safely hook this code in appconfig.

```from django.apps import apps, AppConfig

class CustomApp(AppConfig):
name = 'foo'

models = apps.get_models()
for model in models:
try:
pass
```

Now all models will get registed automatically. If we go to a model page in admin, it will just show 1 column like this.

This is not informative for the users who want to see the data. We can create a `ListAdminMixin`, which will populate `list_display` with all the fields in the model. We can create a new admin class which will subclass `ListAdminMixin` & `ModelAdmin`. We can use this admin class when we are registering the model so that all the fields in the model will show up in the admin.

```from django.apps import apps, AppConfig

self.list_display = [field.name for field in model._meta.fields if field.name != "id"]

class CustomApp(AppConfig):
name = 'foo'

models = apps.get_models()
for model in models:
try:
pass
```

Now whenever we create a new model or add a new field to an existing model, it will get reflected in the admin automatically.

# How To Install Custom ROMs In Xiamo MiPad?

Mi Pad and other Xiamo devices has Mi UI OS which is a dual boot system. A major problem with this system is it has only ~600 MB of space in 1st partition. Because of this, we cannot install some custom ROMs as they need more space. In this article we will see how to merge both partitions to get more free space and install any custom ROM.

### Install TWRP

Dowload latest recovery from twrp.me. Copy it to android device or push it to android using adb.

```adb push -p twrp-3.1.1-0-mocha.img /sdcard/
```

Now put the device into fastboot mode by pressing Volume down & Power button simultanesouly when you switch it on. When in fastboot mode, flash the downloaded recovery file

```sudo fastboot flash recovery twrp-3.1.1-0-mocha.img
```

Now we can go to recovery mode using adb.

```adb reboot recovery
```

### Merge partitions

Before installing custom ROM, we need to merge partitions so that we will have enough space to install ROM. If you are familiar with parted command, you can directly merge the partitions from terminal in TWRP recovery.

There is also a script which you can flash to do the partition. You can read this guide on mi forum for more information.

After partition is completed, from TWRP go to Wipe -> Advanced wipe -> Select System -> Click on Repair or change file system. Here it should show that free space in system is more than 1GB.

### Install ROM

After partitions are merged, it is straight forward to install any custom ROM. Download a custom ROM like lineage or RR, push it to device and then install it from TWRP. After reboot, you will see the custom ROM booting.

# Django Tips & Tricks #8 - Hyperlink Foreignkey Fields In Admin

Consider `Book` model which has `Author` as foreignkey.

```from django.db import models

class Author(models.Model):
name = models.CharField(max_length=100)

class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author)
```

We can register these models with admin interface as follows.

```from django.contrib import admin

from .models import Author, Book

list_display = ('name', 'author', )

```

Once they are registed, admin page shows `Book` model like this.

While browsing books, we can see `name` and `author`. Here, name field is liked to change view of book. But author field is shown as plain text. If we have to modify author name, we have to go back to authors admin page, search for relevant author and then change name.

This becomes tedious if we spend lot of time in admin for tasks like this. Instead, if author field is hyperlinked to its change view, we can directly go to that page.

Django provides an option to access admin views by its URL reversing system. For example, we can get change view of author model in book app using `reverse("admin:book_author_change", args=id)`. Now we can use this url to hyperlink author field in book admin.

```from django.contrib import admin
from django.utils.safestring import mark_safe

link = '<a href="%s">%s</a>' % (url, book.author.name)
```

Now in the book admin view, author field will be hyperlinked to its change view and we can visit just by clicking it.

Depending on requirements, we can link any field in django to other fields or add custom fields to improve productivity.

# How To Remove Clock From LockScreen/StatusBar?

Last year, I wrote a blog post on how to remove clock from lock screen and status bar if xposed is installed on your android device. You can also do this without xposed if you are using RR(Resurrection Remix) as it comes with a lot of inbuilt customization.

#### Remove Clock From LockScreen

To remove clock from lockscreen, go to Settings -> Configurations -> Lock screen -> Show lock screen lock.

#### Remove Time From StatusBar

To remove clock from status bar, go to Settings -> Configurations -> Status bar -> System UI tuner -> Time -> Dont show this icon.

Once you do this, you will have a clean lockscreen and statusbar without any date or time them.

# Bluetooth Serial Communication Between Ubuntu & Android

Most laptops and smart phones(Android/iPhone) have builtin Bluetooth modules. We can use this bluetooth module to communicate with each other or with other bluetooth modules like HC-05 or HM-10.

In this article, we will learn how to send data between laptop and android bluetooth.

First, we need to pair with a bluetooth device to send information. From Ubuntu, we can pair to a Bluetooth device from Bluetooth settings. Alternatively, we can also use CLI to do the same.

```\$ bluetoothctl
[NEW] Controller 24:0A:64:D7:99:AC asus [default]
[NEW] Device 94:E9:79:BB:F8:3A DESKTOP-C4ECO3K
[NEW] Device 88:79:7E:7B:4C:87 athene
[NEW] Device 94:65:2D:8C:2E:10 OnePlus 5
[NEW] Device 98:0C:A5:61:D5:64 Lenovo VIBE K5 Plus
[NEW] Device AC:C3:3A:A0:CE:EF Galaxy J2
[NEW] Device 98:D3:35:71:02:B3 HC-05

[bluetooth]# power on
Changing power on succeeded

[bluetooth]# agent on
Agent registered

[bluetooth]# default-agent
Default agent request successful

[bluetooth]# scan on
Discovery started
[CHG] Controller 24:0A:64:D7:99:AC Discovering: yes

[bluetooth]# pair 88:79:7E:7B:4C:87
Attempting to pair with 88:79:7E:7B:4C:87
[CHG] Device 88:79:7E:7B:4C:87 Paired: yes
Pairing successful
```

To communicate with paired devices, we will use RFCOMM protocol. RFCOMM is just a serial port emulation and provides reliable data tranfer like TCP.

From ubuntu, lets open a port for communication.

```\$ sudo rfcomm listen /dev/rfcomm0 3
```

From Android, we have to connect to ubuntu. For this, we can use Roboremo app which supports RFCOMM.

```\$ sudo rfcomm listen /dev/rfcomm0 3
Waiting for connection on channel 3
Connection from 88:79:7E:7B:4C:87 to /dev/rfcomm0
Press CTRL-C for hangup
```

Once the connection is established, we can communicate between devices.

In Unix like systems, OS provides a device file as an interface for device driver. To send and read messages from Linux or Mac is as easy as reading and writing to a file.

```# to send message to bluetooth
\$ echo 'hello from ubuntu' > /dev/rfcomm0
```

We can see the received messages on Android

We can also send messages from android and read from ubuntu.

```# to read messages from bluetooth
\$ cat /dev/rfcomm0
hello from android
```

This way, we can communicate with any bluetooth module using a laptop or a smart phone.

# Arduino Programming From Text Editor & Command Line

To program Arduino, we can use Arduino IDE which facilitates writing and uploading code to the board.

If we are using a text editor for programming, it will have lot of customisations which speed up development process. In such case, it is better to use same text editor for arduino programming too.

I use Emacs as IDE and there is arduino mode for emacs which provides syntax highlighting and some useful utilites to write arduino code. We can find such packages for other editors also.

Arduino also provides cli interface to upload code to arduino. To upload code, we need to specify port, board and the code to upload.

In Linux system, to upload a file called `foo.ino`, we can run

```arduino --port /dev/ttyACM0 --board arduino:avr:mega
```

An alternate way is to use platformio, an opensource tool chain for IoT development.

It can be installed using pip.

```pip install platformio
```

Once it is installed, code can be directly uploaded using `ci` command.

```pio ci --board=megaatmega2560 --project-option="upload_port=/dev/ttyACM0" --project-option="targets=upload" foo.ino
```

By this we can use text editor to write code and arduino/platformio to upload code to arduino board.

# Using LSTM-CTC For Complex Script Recognistion

Most Indian languages have strong consonant-vowel structure which combine to give syllables. These syllables are written as one continuous ligature and they require complex text rendering (CTL) for type setting.

Writing OCR (Optical Character Recognistion) software for CTL scripts is a challenging task as segmentation is hard. Because of this overall accuracy drops drastically.

A better approach is to use Connectionist Temporal Classification (CTC) which can identify unsegmented sequence directly as it has one-to-one correspondence between input samples and output labels.

Here is a sample input and output of a RNN-CTC network which takes an unsegmented sequence and outputs labels.

Open source OCR software ocorpy uses BLSTM-CTC for text recognistion. Tesseract started using the same in its latest(4.0) version.

I have trained a model to recognize Telugu script using ocropy and the accuracy is ~99% which is far better when compared to OCR softwares without CTC which are accurate to ~70%.

# Auto Register Subclasses Without Metaclass in Python

In registry pattern, a `registry` maintains global association from keys to objects, so that objects can be reached from anywhere by simple identifier. This is useful for doing reverse lookups.

When building a registry, programmers have to explicitly register each object with registry. Manually building a registry is error prone and it is tedious if there are too many objects to register. It is better to auto register objects if possible.

A commonly used approach is to use inheritance as an organizing mechanism. Create a meta class which will auto register classes and then create base class with this meta class.

```REGISTRY = {}

def register_class(target_class):
REGISTRY[target_class.__name__] = target_class

class MetaRegistry(type):

def __new__(meta, name, bases, class_dict):
cls = type.__new__(meta, name, bases, class_dict)
if name not in registry:
register_class(cls)
return cls

class BaseClass(metaclass=MetaRegistry):
pass

class Foo(BaseClass):
pass

class Bar(BaseClass):
pass
```

Now whenever you subclass `BaseClass`, it gets registered in the global registry. In the above example, `Foo`, `Bar` gets registered automatically.

Eventhough it solves registration problem, it is hard to understand the code unless you know how metaclasses work.

A simple alternative for this is to use `__subclasses__()` to get subclasess and register them.

```REGISTRY = {cls.__name__: cls for cls in BaseClass.__subclasses__()}
```

This will work only for direct subclasses and won't with indirect subclasses like this.

```class Baz(Bar):
pass
```

To solve this, we can use a function to recursively retrieve all subclasses of a class.

```def subclasses(cls, registry=None):
if registry is None:
registry = set()

subs = cls.__subclasses__()

for sub in subs:
if sub in registry:
return
yield sub
for sub in subclasses(sub, registry):
yield sub

REGISTRY = {cls.__name__: cls for cls in subclasses(BaseClass)}
```

PEP 487 provides `__init_subclass__` hook in class body to customize class creation without the use of metaclass. We can our registration logic in this `__init_subclass__` hook.

```class BaseClass:
def __init_subclass__(cls, **kwargs):
if cls not in registry:
register_class(cls)
super().__init_subclass__(**kwargs)

print(registry)
```

This is available only in Python 3.6+. For older versions, we have to use the recursive function to get all subclasess. This code is easier to understand than metaclass example.

# How To Auto Reload Celery Workers In Development?

We can pass `--autoreload` option when starting celery worker. This will restart worker when codebase changes.

```celery worker -l info -A foo --autoreload
```

Unfortunately, it doesn't work as expected and it is deprecated.

During development, we will keep on changing the code base. Manually restarting celery worker everytime is a tedious process. It would be handy if workers can be auto reloaded whenever there is a change in the codebase.

Watchdog provides Python API and shell utilities to monitor file system events. We can install it with

```pip install watchdog
```

Watchdog provides `watchmedo` a shell utilitiy to perform actions based on file events. It has `auto-restart` subcommand to start a long-running subprocess and restart it. So, celery workers can be auto restarted using this.

```watchmedo auto-restart -- celery worker -l info -A foo
```

By default it will watch for all files in current directory. These can be changed by passing corresponding parameters.

```watchmedo auto-restart -d . -p '*.py' -- celery worker -l info -A foo
```

If you are using django and don't want to depend on watchdog, there is a simple trick to achieve this. Django has autoreload utility which is used by `runserver` to restart WSGI server when code changes.

The same functionality can be used to reload celery workers. Create a seperate management command called `celery`. Write a function to kill existing worker and start new worker. Now hook this function to autoreload as follows.

```import shlex
import subprocess

from django.core.management.base import BaseCommand

def restart_celery():
cmd = 'pkill -9 celery'
subprocess.call(shlex.split(cmd))
cmd = 'celery worker -l info -A foo'
subprocess.call(shlex.split(cmd))

class Command(BaseCommand):

def handle(self, *args, **options):
Now you can run celery worker with `python manage.py celery` which will start a celery worker and autoreload it when codebase changes.