Month: October 2012

Soldando placas BGAs em casa

Zach Hoeken criou um processo e postou um ótimo artigo explicando como soldar placas SMDs em casa usando um stencil (que também pode ser construído usando remoção a laser ou acido) :

http://www.hoektronics.com/2012/10/27/super-simple-smt-stencil8/#comment-111

O interessante deste post é que ele usou um forno próprio para soldar SMD, o T-962A da Tech168:

http://www.tech168.cn/EN/product1.asp?xq_id=670

Segundo o Zach este forno custou algo em torno de $200.00 em Shenzhen.

How to transfer files to a Linux embedded system over serial

Imagine a scenario where you have a device running an embedded Linux system, but you flashed a bad firmware which doesn’t let you to have access to Ethernet/WiFi on this device. You only have access to it is using serial cable.

First thing you think is to use U-Boot transfer support over serial, but unfortunately you don’t have this option:

U-Boot 1.1.4 (Feb 27 2009 - 12:06:20)

AP94 (ar7100) U-boot 0.0.12
(sic)
In:    serial
Out:   serial
Err:   serial
Net:   eth0, eth1
### main_loop entered: bootdelay=1

### main_loop: bootcmd="bootm 0xbf050000"
Hit any key to stop autoboot:  0 
### main_loop: got key string, abort boot
### main_loop: no define CONFIG_AUTOBOOT_KEYED
### main_loop: CFG_HUSH_PARSER
### main_loop: parse_string_outer
## Booting image at bf050000 ...
checksum:743d0796
   Image Name:   MIPS OpenWrt Linux-2.6.39.4
   Image Type:   MIPS Linux Kernel Image (lzma  compressed)
   Data Size:    873389 Bytes = 852.9 kB
   Load Address: 80060000
   Entry Point:  80060000
   Verifying Checksum ... OK
   LZMA Umcompressing Kernel Image ...    Image loaded from 80060000-802e82d8

As you can see it is not entering on U-Boot prompt because CONFIG_AUTOBOOT_KEYED is not defined.

Then we need to find another alternative.

Unfortunately we are not lucky, the linux system on this router doesn’t have “lrz” program installed.

But all is not lost, I have an idea!!!

The “lrz” program is relatively small, about 60KB, then I can convert it to text and past on Linux terminal running inside de box (using echo and pasting text). Unfortunately I cannot use base64 program, because it also is not install on this Linux system.

The remaining option is using hexdump (xxd) to convert the binary on text bytes and the recover it, as I suggested some times ago (link in Portuguese).

So, let to do it, first thing to do is download the package containing the lrz program (lrzsz_0.12.20-1_ar71xx.ipk).

Hmm, this is 59792 bytes long, no problem I hope.

Now let to convert it from binary to text:

$ xxd -g1 lrz > output.txt

We need to remove the “00xxxxx: ” from beginning of each line and the 16 chars representation at end of each line:

$ sed -i 's/^\(.\)\{9\}//g' output.txt
$ sed -i 's/\(.\)\{16\}$//g' output.txt

Now let to convert this text back to binary to confirm it is working:

$ for i in $(cat output.txt) ; do printf "\x$i" ; done > mylrz

Let to check if they are have same binary sequence:

$ md5sum mylrz 
08334803ce751a1f021a4de0c9c0e849  mylrz
$ md5sum lrz 
08334803ce751a1f021a4de0c9c0e849  lrz

Now just let to copy and past this content of text to linux box terminal.

I suggest you to use picocom instead minicom to do it:

$ picocom -b 115200 -l -r /dev/ttyUSB0

I started trying to send line by line this way:

root@OpenWrt:/# echo "7f 45 4c 46 01 02 01 00 01 00 00 00 00 00 00 00" >> mylrz.txt

In few seconds it became a very boring task and very prone to fail.

Then I decide to send commands directly to terminal over serial using shell script.

Leave picocom…

After some tests I noticed it is not possible to send many characters to terminal (over /dev/ttyUSB0), no more 2 bytes by time.

Then the command became this long line:

$ j=0; echo -n -e "ec" > /dev/ttyUSB0; echo -n -e "ho" > /dev/ttyUSB0; echo -n -e " \"" > /dev/ttyUSB0; for i in $(cat output.txt); do j=$(($j+1)); echo -n -e "$i" > /dev/ttyUSB0; echo -n -e " " > /dev/ttyUSB0; if [ $(expr $j % 16) -eq 0 ]; then echo -n -e "\" " > /dev/ttyUSB0; echo -n -e ">>" > /dev/ttyUSB0; echo -n -e "lr" > /dev/ttyUSB0; echo -n -e "z" > /dev/ttyUSB0; echo " " > /dev/ttyUSB0; echo -n -e "ec" > /dev/ttyUSB0; echo -n -e "ho" > /dev/ttyUSB0; echo -n -e " \"" > /dev/ttyUSB0; fi; done; echo -n -e "ec" > /dev/ttyUSB0; echo -n -e "ho" > /dev/ttyUSB0; echo "\"" > /dev/ttyUSB0

Verify if file lrz file was created:

root@OpenWrt:/# ls -l lrz
-rw-r--r--    1 root     root        183113 Jan  1 01:19 lrz

Rename it to lrz.txt:

root@OpenWrt:/# mv lrz lrz.txt

Convert the text file to binary:

root@OpenWrt:/# for i in $(cat lrz.txt) ; do printf "\x$i" ; done > lrz
root@OpenWrt:/# md5sum lrz
08334803ce751a1f021a4de0c9c0e849  lrz

Give it permission to execute and move to /usr/bin:

root@OpenWrt:/# chmod 555 lrz
root@OpenWrt:/# mv lrz /usr/bin/

Execute the lrz command to receive file:

root@OpenWrt:/# lrz -Z

Leave picocom program (Ctrl+A+X)

In you computer execute this command to transfer firmware to your router:

$ sz --zmodem /tmp/openwrt-ar71xx-dir825.bin > /dev/ttyUSB0 < /dev/ttyUSB0

Check with md5sum to verify if it is correct:

root@OpenWrt:/tmp# md5sum openwrt-ar71xx-dir825.bin 
90e938ed4a5aa825495c2b0b099655e7  openwrt-ar71xx-dir825.bin

alan@aureo:~/Desktop/serial$ md5sum /tmp/openwrt-ar71xx-dir825.bin 
90e938ed4a5aa825495c2b0b099655e7  /tmp/openwrt-ar71xx-dir825.bin

Now just update your system using this new firmware:

root@OpenWrt:/# sysupgrade /tmp/openwrt-ar71xx-dir825.bin

How to install JDK 1.6 on Ubuntu in order to compile Android System

Unfortunately there is not a java 1.6 package available on Ubuntu repository, but fortunately we have an alternative:

https://github.com/flexiondotorg/oab-java6

$ git clone https://github.com/flexiondotorg/oab-java6.git
$ cd oab-java6
$ sudo ./oab-java.sh

If compilation finished correctly just execute it:

$ sudo apt-get install sun-java6-jdk

Case you have other java packages installed, execute it:

$ sudo update-alternatives --config java

and choose number related to /usr/lib/jvm/java-6-sun/jre/bin/java and repeat this process to javac.

Thanks Vinicius Tinti for this tip.

Simplificando o debug durante o porte de aplicativo Linux para Android

Por padrão quando um programa compilado para Android tenta escrever no stdout/stderr nada é exibido no console do Android e nem no no buffer do logcat, você precisa usar as macros LOGx (LOGE, LOGD, etc) ou invés de usar printf e semelhantes.

Felizmente existe um jeito de redirecionar a saida do stdout/stderror para o logcat usando estes comandos:

$ adb shell stop
$ adb shell setprop log.redirect-stdio true
$ adb shell start

Fonte: http://raymondlo84.blogspot.ca/2012/09/enable-stdout-and-stderr-for-debugging.html

Controlando o recebimento de encomendas

Se você é aquele tipo de pessoa que a cada 5 minutos acessa o site dos correios só para ver se o status da sua encomenda mudou, então esta dica com certeza vai te interessar.

Existe um site onde você pode cadastrar o código de rastreamento da sua encomenda e toda vez que o status da encomenda mudar ele te envia um email avisando, este site é o http://www.muambator.com.br

Assim caso você tenha algum problema para receber sua encomenda poderá contactar o agência dos correios do seu bairro para agendar uma entrega ou buscar pessoalmente.

O site é gratuito e mantem-se no ar graças às doações dos colaboradores, então se suas encomendas chegaram corretamente e você ficou mais tranquilo graças ao muambator, não esqueça de fazer sua doação.

Reading microphone audio using pulseaudio-simple

This example is a modified version from audio microphone input from julius ASR.

I’m using it to read audio samples from microphone and printing bytes directly to screen:

/**
 * Copyright (c) 2010-2012 Julius project team, Nagoya Institute of Technology
 * All rights reserved
 */

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stddef.h>
#include <unistd.h>
#include <pulse/simple.h>
#include <pulse/error.h>

#define BUFSIZE 32

#define RATE 44100

//#define RATE 16000

int16_t buffer[BUFSIZE];

static pa_simple *s = NULL;
static char name_buf[] = "PulseAudio default device";

/** 
 * Connection initialization: check connectivity and open for recording.
 * 
 * @param sfreq [in] required sampling frequency
 * @param dummy [in] a dummy data
 * 
 * @return TRUE on success, FALSE on failure.
 */
int adin_pulseaudio_standby(int sfreq, void *dummy)
{
  return 0;
}
 
/** 
 * Start recording.
 * @a pathname is dummy.
 *
 * @param arg [in] argument
 * 
 * @return TRUE on success, FALSE on failure.
 */
int adin_pulseaudio_begin(char *arg)
{
  int error;

  static const pa_sample_spec ss = {
  	.format = PA_SAMPLE_S16LE,
  	.rate = RATE,
  	.channels = 1
  };
  
  if (!(s = pa_simple_new(NULL, "Julius", PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) {
    printf("Error: adin_pulseaudio: pa_simple_new() failed: %s\n", pa_strerror(error));
    return 1;
  }
  return 0;
}

/** 
 * Stop recording.
 * 
 * @return TRUE on success, FALSE on failure.
 */
int adin_pulseaudio_end()
{
  if (s != NULL) {
    pa_simple_free(s);
    s = NULL;
  }
  return 0;
}

/**
 * @brief  Read samples from device
 * 
 * Try to read @a sampnum samples and returns actual number of recorded
 * samples currently available.  This function will block until
 * at least one sample was obtained.
 * 
 * @param buf [out] samples obtained in this function
 * @param sampnum [in] wanted number of samples to be read
 * 
 * @return actural number of read samples, -2 if an error occured.
 */
int adin_pulseaudio_read (int16_t *buf, int sampnum)
{
  int error;
  int cnt, bufsize;

  bufsize = sampnum * sizeof(int16_t);
  if (bufsize > BUFSIZE) bufsize = BUFSIZE;

  if (pa_simple_read(s, buf, bufsize, &error) < 0) {
        printf("Error: pa_simple_read() failed: %s\n", pa_strerror(error));
  }
  cnt = bufsize / sizeof(int16_t);
  return (cnt);
}


int main()
{
	adin_pulseaudio_begin("nothing");


while(1)
{
	adin_pulseaudio_read(buffer, 32);

        /* And write it to STDOUT */
        if (write(STDOUT_FILENO, buffer, 32) != 32) {
            fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno));
            goto finish;
        }
	usleep(5);
}

finish:
	adin_pulseaudio_end();

	return 0;
}

You can compile this way:

$ gcc micpa.c -o micpa $(pkg-config --cflags --libs libpulse-simple)

Execute this command to write sound from microfone

$ ./micpa > test.raw

Convert test.raw to wave file:

$ sox -t raw -b 16 -e signed-integer -r 44100 test.raw test.wav

Now you can play test.wav to listen your recorded voice.