[AKM Chip Booster] Audio ADC AK5704 PCB Design

Designing a PCB prototype with AK5704 is not so difficult and I show an example with my design.
People who are not familiar with AK5704, please read my previous post.

I listed some useful information here just in case you want to skip my previous post 🙂 


Let me share the picture of the board that I designed.




For this design, I wanted to have both analog and digital input path, so I added 3.5mm audio jacks (J1-J4) and small connectors (J6-J9).
Power supply is 3V or 5V so that I can use Raspberry Pi or Arduino.

Here is the quick features with this board.
  • Connectors
    • Analog input connector: 3.5 mm audio jack x 4
    • Digital input: 5 pin 1.0 mm pitch connector x 4
    • Host interface: 16 pin 2.54 mm pitch header x 1
  • Power supply: 3V or 5V
  • ADC input: Single-ended or differential input
  • Audio interface: I2S (TDM, PCM)
  • Control interface: I2C
    • I2C address is selectable by resister

It is currently debugging and not 100% sure everything works.
If you are interested in the schematic, please contact me and I might consider sharing the schematic if I feel comfortable 🙂


Notes:
As of 4/11/2020, analog input is working and I was able to stream the audio using Raspberry Pi ❕❕❕

[AKM Chip Booster] AK5704 Low-Power 4-ch 32-bit ADC with MIC-Amp


AK5704 is an audio ADC with microphone amplifier. It has 4 channel and 32 bit resolution.
You can get the information including the datasheet from AKM website.

I listed some useful information here.

According to this article, they built a smart speaker demo using AK5704 and the demo was displayed during the CES 2018. 
News release date in the above link is stated as 2019/06/11, so I guess it officially became available nearly 1.5 years after the CES demo in 2018.

Application using AK5704 includes:
  • Conference system
  • Microphone array system
  • Smart speaker
  • Baby or pet monitor
  • IC recorder

Parts are available from Digikey although the evaluation board is not available.
The chip price is $2.36/pcs (as of 4/11/2020), so it is quite reasonable for the people who want to prototype.


Notes:
QFN package with 28 pins so it is possible to hand solder the chip for the people who want to save the money 🙂
However, the exposed pad is a concern as it should be connected to the ground.
Maybe you can solder the pad easily by PCB design considering more grounding traces to the exposed pad. I don't know....



Also check:

[Raspberry Pi] Power Monitor


Power Consumption Monitor using Raspberry Pi


Sometimes I get tired of using test equipment to monitor the current and/or power consumption of the system, especially when I want to quickly test it and log the data.
For some of my projects, I use INA219 populated on my board to monitor the current.
Yes, it is very helpful and I can manage the power status through firmware.
Also, having test equipment is not practical for the hobby projects like I do...
So here, I decided to use off-the-shelf INA219 board with Raspberry Pi to create easy and cheap current and/or power monitoring tool.
I bought Adafruit INA219 board and this is just less than $10. 
Here is the features.
  • 0.1 ohm 1% 2W current sense resistor
  • Up to +26V target voltage
  • Up to ±3.2A current measurement, with ±0.8mA resolution
If you want even cheaper INA219 board, there are some others and I think those work very similar to Adafruit one.
Less than $5:


Setup
For this setup, I am using Raspberry Pi 3 Model B.
Thankfully, there are many tutorials and information already.
You can refer to the Adafruit site for the hardware and software instructions.

1. Connect INA219 board to Raspberry Pi
I used jumper wires to connect 2 boards.
You just need 4 wires and check the diagram here for the connection.
  • RPI pin1(3V3) to INA219 Vcc pin 
  • RPI pin3(SDA) to INA219 Sda pin
  • RPI pin5(SCL) to INA219 Scl pin
  • RPI pin9(GND) to INA219 Gnd pin

2. Install Python module
For those people using Python v3, you can use CircuitPython module.
You can follow the same Adafruit page above and there are sample codes.
I am using Python v2, so I used the library called pi-ina219.
Simple command. Just run below to install the library.

$ sudo pip install pi-ina219
3. Sample code test
pi-ina219 library page has sample code.
I simply tried the first sample and it works.
You will see the 4 printed values in your terminal.
If you see errors, make sure wires are connected properly.


                             


Here is 2 more test codes that I basically added to the above sample code.

Reading continuously:

#!/usr/bin/env python
from ina219 import INA219
from ina219 import DeviceRangeError

SHUNT_OHMS = 0.1
ina = INA219(SHUNT_OHMS)
ina.configure()

def read():

    BV = ina.voltage()
    BC = ina.current()
    PW = ina.power()
    SV = ina.shunt_voltage()
    print("Bus Voltage: %.3f V" % BV)
    try:
       print("Bus Voltage: %.3f V" % BV)
        print("Bus Current: %.3f mA" % BC)
        print("Power: %.3f mW" % PW)
        print("Shunt voltage: %.3f mV" % SV)
    ina.sleep()
    time.sleep(3)
    ina.wake()
    except DeviceRangeError as e:
        # Current out of device range with specified shunt resister
        print(e)


if __name__ == "__main__":
    while True:
        read()

Logging data:

#!/usr/bin/env python
from ina219 import INA219
from ina219 import DeviceRangeError
import time
import csv
import os

SHUNT_OHMS = 0.1
ina = INA219(SHUNT_OHMS)
ina.configure()

file = open("log.csv", "a")

def read():

    IV = ina.supply_voltage()
    BV = ina.voltage()
    BC = ina.current()
    PW = ina.power()
    SV = ina.shunt_voltage()
    print("Supply Voltage: %.3f V" % IV)
    try:
       print("Bus Voltage: %.3f V" % BV)
        print("Bus Current: %.3f mA" % BC)
        print("Power: %.3f mW" % PW)
        print("Shunt voltage: %.3f mV" % SV)
        with open("log.csv", 'a') as log:
        writer = csv.writer(log, delimiter=",")
        writer.writerow([time.time(), IV, BV, BC, PW, SV])
    ina.sleep()
    time.sleep(3)
    ina.wake()
    except DeviceRangeError as e:
        # Current out of device range with specified shunt resister
        print(e)


if __name__ == "__main__":
    if os.stat("log.csv").st_size == 0:
        file.write("Time, Supply Voltage(V), Bus Voltage(V), Bus Current(mA), Power(mW), Shunt Voltage(mV)\n")
    file.close()
    while True:
        read()


How to install Chainer for your deep learning projects


Installing Chainer for Your Deep Learning Projects


I think many people use TensorFlow for deep learning projects and I was thinking about it as well.
However, I changed my mind somehow and decided to use Chainer.
Chainer is developed by Japanese company called Preferred Networks (PFN).
How is the performance? 
Well, according to them, image classification training using ImageNet data set took the least time compared with other frameworks like MXNet, CNTK, TensorFlow.
I think there are pros and cons between the frameworks but just decided to use it as I am also Japanese Fan :)
I will go through how to setup Chainer environment using Windows. 
However, it applies to Linux as well since I am actually using Linux on top of virtual machine.
It is so easy so hope people try it and start using Chainer!

Setup
As I mentioned before, I am using Windows.
If you have Linux machine, you can skip step 1-3 and just install Chainer.

1. Install VirtualBox
First I installed VirtualBox which is a virtual machine.
You can install it from VirtualBox website.
Download VirtualBox and install it.
    *** I downloaded VirtualBox 5.2

2. Download Ubuntu image
Next is to download Ubuntu image and this will be your Linux environment for deep learning.
Download the image from Ubuntu website.
    ***I downloaded Ubuntu18.04 64-bit

3. Add Ubuntu to VirtualBox
Click [New] to create a virtual machine and select [Expert Mode] if it is not displayed as [Expert Mode].
In "Name and operation system", follow this.

    Name: whatever you want to name this virtual machine
    Type: Linux
    Version: Ubuntu (64-bit)

Keep other areas as is and click [Create].


Click the folder icon in "File location" and select any location that you want to keep VirtualBox system files for this virtual machine. (Log and others)

Set "File size" to 16GB or 32GB.
Click [Create] and this will add new virtual machine to the left side of your VirtualBox main screen.

3. Install Ubuntu
Select virtual machine name that you created and click "Start".
It will ask for Ubuntu image and choose the Ubuntu image that you downloaded.
After this, it is just normal Ubuntu installation process and you can follow the instructions.

4. Install Chainer
Okay, now we can install Chainer and here is how.

    $ sudo apt-get install python-pip
    $ sudo pip install --upgrade pip
    $ sudo pip install chainer==3.2.0
    $ sudo apt-get install python-matplotlib
    $ sudo apt-get install graphviz
    $ sudo apt-get install python-tk



Test
To test If you have successfully installed Chainer, we can use Chainer official sample program.

    $ wget https://github.com/chainer/chainer/archive/v3.2.0.tar.gz
    $ tar xzf v3.2.0.tar.gz
    $ cd chainer-3.2.0/examples/mnist
    $ python train_mnist.py

after this, you will see test results in the terminal.

Now you can start using Chainer!
You can find lots more in Chainer website

[Raspberry Pi] Bluetooth Audio Headphone

Bluetooth Audio Device with Raspberry PI


Raspberry pi with Bluetooth again.
Last time I connected my DualShock 4 controller to raspberry pi.
This time, my motivation was to use Bluetooth audio headset using Raspberry pi.
I am not sure if this will give me any new project ideas.
Many people have already managed streaming Bluetooth audio from the raspberry pi.
There are a lot of creative projects available.
I hope I can make something unique by learning the Bluetooth audio with raspberry pi.

Setup
I was thinking this would be super easy and just need to work on the pulseaudio. 
This was a bad thought...
Because of this, I created unnecessary problems and took me about 3 hours to make it work.
I added "Note" at the very end of this post if you are interested in what happened.
Anyway, what I learned was that Bluetooth is a little bit tricky depending on the hardware and OS version.
I would highly recommend to double check the hardware and software versions before you start.
    This is the one of the great site to read through.

1. Check hardware version
Hardware version can be referred from cpuinfo file.
$ cat /proc/cpuinfo
When the information is displayed, you can scroll down and find the "Hardware" and "Revision" info.
In my case:
Hardware    : BCM2835
Revision      : a02082

For the relationship between the raspberry pi model and revision number, you can refer to this
I am referring to new style revision code and my hardware is model 3B.
a02082 3B 1.2 1GB Sony UK

If your model is 3B+ with latest raspbian image, I think you can simply follow this.

2. Check OS version
For OS version, you can check os-release file. 
$ cat /etc/os-release

My version is "Stretch". 


3. Testing
You can use desktop Bluetooth icons to pair and connect the device, but here I tried with bluetoothctl.
$ bluetoothctl
After running the bluetoothctl, you can turn on the agent and set it to the default.
agent on
default-agent
Now you are ready to scan the BT devices, and set the headset to pairing mode.
Then type the following command in the bluetoothctl terminal.
scan on

Once your headset is discovered, you will see something like this in the terminal.
[NEW] Device XX:XX:XX:XX:XX:XX  

"XX:XX:XX:XX:XX:XX" is your controller MAC address and type the following command with the MAC address.
Connect XX:XX:XX:XX:XX:XX

Once you see the message "Connection successful", your headset is connected, and last thing you may want to do is remember the device so that it is automatically connected next time.
Trust XX:XX:XX:XX:XX:XX

Now you are ready, and you can close the bluetoothctl by typing "quit".
Before play any audio file, make sure the Bluetooth audio device is selected as playback device.
To do so, right click the volume icon and select the device you want to send the audio.
Try play the audio file, youtube, or any others, and you will hear the audio from your headset! 

You can disconnect the controller from upper right BT icon by selecting "Headset name" > "Disconnect".

Note:
As I mentioned previously, I made big mistake by installing pulseaudio.
Somehow, I was thinking pulseaudio is the must and installed it without checking anything.
Then, I paired my Bluetooth headset without any problem.
I can see my desktop BT icon as connected to the device I want.
Audio device is selected through volume control icon.
However, I could not hear anything...

I run the command "pacmd" to  "list-cards" and what I noticed was there is no BT device indexed...
Just alsa device... hmm...

Then I killed pulseaudio process and restarted, run the "systemctl" command to check the status.
$ sudo systemctrl status bluetooth*

The error message I got was something like below. 
            bluetoothd "unable to get connect data for headset"
From this point, I spend lots of time to solve issue by looking at system, config, and other files.
Until, until I actually found that just simply remove the pulseaudio.
It is always better to read RaspberryPi.org documentation...
It says:
In Jessie, we used PulseAudio to provide support for audio over Bluetooth, but integrating this with the ALSA architecture used for other audio sources was clumsy. For Stretch, we are using the bluez-alsa package to make Bluetooth audio work with ALSA itself. PulseAudio is therefore no longer installed by default, and the volume plugin on the taskbar will no longer start and stop PulseAudio. From a user point of view, everything should still work exactly as before – the only change is that if you still wish to use PulseAudio for some other reason, you will need to install it yourself.

So for the people who see the similar errors, please try removing the pulseaudio ;)
$ sudo apt-get remove --purge pulseaudio

After removing pulseaudio, you can check the bluetooth status with "systemctl" and it should be working now.

Some people might still want to use pulseaudio.
If that is the case, this blog by Youness might help.

Good luck and thank you for reading!




[Raspberry Pi] Servo Control Using DS4 Controller

Raspberry Pi servo control using DS4 controller

In the previous post here,  I successfully connected DS4 controller to Raspberry Pi.
It is time for me to control something using this framework.
The easiest way for me is to control the servo using DS4 input events as I have the servo controller board and tilt & pan servos from Adafruit.
My goal is to use joystick on the DS4 to control the pan & tilt of servo and see how it works.
I expect it would not be so great using joystick as it is a bit sensitive and may be difficult to control servo naturally or precisely. 
Well, let's see how it goes...


Setup
As always, I am using Raspberry Pi 3 Model B (not Plus) for this setup.
The setup looks like this in my environment.
Connecting DS4 to Raspberry Pi can be referred to my previous work here
Also, the using Adafruit servo controller shield board and pan & tilt servo kit can be referred to my previous work here as well.

Adafruit servo controller shield board requires the external power supply but you may be able to use Raspberry Pi 5V by connecting the power and ground pins to the shield board depending on the servo you use.


                          


My approach:
My approach here is to obtain the variation from the default (center) position of the joystick data and convert the number to the servo control signal with a simple scale factor.
Something like this.

    Servo value = (Joystick current value - Joystick center value) x scale factor

To do this, I need to understand the DS4 joystick operation and range of the return values.

There are so many descriptions if you google it but what I did was to add the following line in the python. 

    print (gamepad.capabilities(verbose=True))

This will give you the default value and maximum and minimum value of the each event of the input device.

From this message, left joystick returns 127 as the center value and maximum 255 and minimum 0. 

This means the maximum variation value that I get from joystick is 128 and minimum is -127.

    Maximum variation value = 255 - 127 = 128

    Miminum variation value = 0 - 127 = -127

I just want to move the servo around +/-90 degrees horizontally, and my servo range is as below.

    +90: 570
    0: 370    
    -90: 170

Based on the above, I decided the equation to be like this.

    Servo value = (Joystick current value - 127) x 1/10

One thing that I cannot forget is that I am using evdev and it only returns the input event when there is a change in the value.

This means if I move the joystick to the all the way left or right, the joystick value does not change from the point which results in no servo movement. 



Notes:
Before moving forward, I would recommend to double check the minimum and maximum rotations of your servo. 
Joystick is sensitive and servo might go crazy if the tuning is not done properly.
I would also recommend to place the servo securely with something.

In my case, I used cramp and place it on my desk tightly.


Python code for testing
Now the time to implement the code for both DS4 joystick and servo control.
As I mentioned above and same as my previous work, I used evdev and python for this quick example.
    *** Depending on the python version, you may get different result and my python version is 2.7.13.

If you need the input event numbers of your controller, you can use the following commands to idendify the numbers.


Check input events:
$ ls /dev/input

Install input-utils:
If you do not know which event is mouse or keyboard, follow this.

$ sudo apt-get install input-utils
$ lsinput    

Video:
Here is the video of the quick test.
 

Example:

This is the python example code.

#!/usr/bin/python

from Adafruit_PWM_Servo_Driver import PWM
import time

from evdev import InputDevice, categorize, ecodes, KeyEvent
gamepad = InputDevice('/dev/input/event7')
absMed = 128

pwm = PWM(0x40)

servo0Min = 60
servo0Mid = 360
servo0Max = 660

pwm.setPWMFreq(60)
pwm.setPWM(0, 0, servo0Mid)
time.sleep(1)

step0 = servo0Mid
step0Var = 0

for event in gamepad.read_loop():
    if event.type == ecodes.EV_ABS:
 if event.code == 0 and abs(event.value-absMed) > 20:
  step0Var = (event.value - absMed)/10
  print ('step0Var:' + str(step0Var))
  print ('step0   :' + str(step0))
      step0 += step0Var
  if step0 > servo0Max:
   step0 = servo0Max
  elif step0 < servo0Min:
   step0 = servo0Min
      pwm.setPWM(0, 0, step0)
  step0Var = 0

Crate a python script file as below and copy&paste the above code.
nano ds4-servo-test.py
Run the python script.
python ds4-servo-test.py
Press any buttons on the DS4 and you will see the outputs in the terminal.
Done!



[AKM Chip Booster] Audio ADC AK5704 PCB Design

Designing a PCB prototype with AK5704 is not so difficult and I show an example with my design. People who are not familiar with AK5704,...