Programming – Deep Focus https://fazals.ddns.net/ Embrace it! Thu, 04 Feb 2021 09:07:01 +0000 en-US hourly 1 https://wordpress.org/?v=5.6.1 https://fazals.ddns.net/wp-content/uploads/2020/08/react-native-300-150x150.png Programming – Deep Focus https://fazals.ddns.net/ 32 32 173186184 Sampling theorem | Verification of NYQUIST’S sampling theorem using MATLAB https://fazals.ddns.net/sampling-theorem-nyquists-theorem-using-matlab/ Thu, 04 Feb 2021 08:18:32 +0000 https://fazals.ddns.net/?p=3168

We all know that there are two kinds of signals:
1. Analog Signals
2. Digital Signals
We know that the signals that exists in nature are analog by default. And we also know that the signals that we store on our computers and memory devices like pen-drives, hard disks, SD cards and so on are of-course digital in nature.
Now the question that might come to your mind:

how do you convert an analog signal to a digital signal?

The answer to that is simple, first we sample the analog signal, and then we quantize it. Sampling is a process where in you hold the analog signal’s amplitude for a brief amount of time, so that the continuous time and continuous valued signal, becomes discrete time, continuous valued signal.

Sampling Theorem
The given image simply demonstrates how an analog signal in sampled.

Sampling Theorem

Now, there’s a theorem that governs the sampling process. Harry Nyquist, a Swedish electronic engineer came up with it. Now, it’s known as the sampling theorem.

Sampling Theorem states that the minimum sampling rate for an analog signal, when uniformly sampled is two times that frequency of the analog signal being sampled. Or in simple words, the sampling frequency must be twice that of the signal being sampled.

This minimum frequency, or the sampling rate is also called as the Nyquist rate.

Proving Sampling Theorem in MATLAB.

So basically, we need to prove that when a signal is sampled at a frequency less than the Nyquist Sampling rate, proper recovery of the signal is not possible. We can easily prove it in the frequency domain. When the sampling frequency is less than Nyquist Rate, we can show that the recovered signal’s frequency is not same as that of the actual analog signal.

MATLAB Code to prove Nyquist Sampling Theorem

You can download the complete code at the end of this post.

Before we start, we make sure that the workspace is cleaned.

clear all;
close all;
clc;

Next, we initialize all the required variables

widthOfTheLine = 1.5;
numberOfWaves = 5; % Number of waveforms to be shown
messageSignalFrequency = input("Enter the Message Signal Frequency: "); % Taking the user's input for Message Signal Frequency
initialSamplingFreq = 50*messageSignalFrequency; % Sampling Frequency for Unsampled Signal
timePerSample = 1/initialSamplingFreq; % Time needed for a single sample
stopTime = 1; % Samples to be generated up to.
timeAxis = 0:timePerSample:stopTime-timePerSample; % Generating the time axis
totalNumberOfSamples = size(timeAxis,2); % Calculating the number of samples
samplingFrequencyInterval = initialSamplingFreq/totalNumberOfSamples; % Calculating the frequency interval to generate the frequency axis;
frequencyAxis = -initialSamplingFreq/2:samplingFrequencyInterval:initialSamplingFreq/2-samplingFrequencyInterval; % Generating the Frequency Axis
phiDegrees = 90; % in degrees
phi = phiDegrees * pi / 180;
  1. widthOfTheLine – It is the width of the line on the plot.
  2. numberOfWaves – Number of waves of the signal to be shown on the plot.
  3. messageSignalFrequency – Frequency of the signal to be sampled.
  4. initialSamplingFreq – It is 50 times that of the message signal frequency, just to show the unsampled analog signal as smooth as possible.
  5. stopTime – Samples will be generated up to stopTime.

We take a 90 degree phase shift so as to avoid the “0” sampled signal value for a perfectly sampled signal. You could easily replace the sin with a cos function and avoid adding the phase shift to the signal.

Check Out my other Posts

]]>
3168
Blynk OTA on NodeMCU, ESP8266, ESP32 and more | PlatformIO | Blynk OTA simplified. https://fazals.ddns.net/blynk-ota-arduino-nodemcu-esps/ Sat, 20 Jun 2020 08:53:41 +0000 https://fazals.ddns.net/?p=2217 Blynk OTA on NodeMCU, ESP8266, ESP32 and more | PlatformIO | Blynk OTA simplified. Read More »

]]>
We all know that the Blynk app together with tiny micro controllers is an amazing combination for IoT. NodeMCU, ESP8266, ESP32 and many other Arduino boards are compatible with the Blynk platform. With such large support, Blynk OTA would be a over whelming feature. The code uploading and testing of the device is simple when in the prototype stage. But, when you have a completed the design and development and have no access to the serial port over the USB, you can no longer upload new codes and updates to the devices without breaking them apart.

But is it possible to have the Blynk code updated the over the air (OTA)?

Well officially, the Blynk Platform doesn’t support the OTA updates. They do have it, but with “0” compatibility, making it of no use. They might develop it in the future, but the wait is never over.

Don’t have Arduino IDE, download Arduino IDE from their official website.

The solution for Blynk OTA over WiFi

Do you know that the Arduino OTA library, helps in uploading the code to any device over the network. Well if you don’t. Yeah, it does, using the TCP/IP protocol.

The Arduino OTA code

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

#ifndef STASSID
#define STASSID "your-ssid"    //put your WiFi SSID (Name)
#define STAPSK  "your-password"    //Set your WiFi Password
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

void yourSetup(){
  //put your code that need to run once
}

void yourLoop(){
  //put the code that needs to run continuously
}

void setup() {
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  // Port defaults to 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  // ArduinoOTA.setHostname("myesp8266");

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else { // U_FS
      type = "filesystem";
    }

    // NOTE: if updating FS this would be the place to unmount FS using FS.end()
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) {
      Serial.println("Auth Failed");
    } else if (error == OTA_BEGIN_ERROR) {
      Serial.println("Begin Failed");
    } else if (error == OTA_CONNECT_ERROR) {
      Serial.println("Connect Failed");
    } else if (error == OTA_RECEIVE_ERROR) {
      Serial.println("Receive Failed");
    } else if (error == OTA_END_ERROR) {
      Serial.println("End Failed");
    }
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  yourSetup();
}

void loop() {
  ArduinoOTA.handle();
  yourLoop();
}

The code is exactly same as provided in the examples in the Arduino IDE with slight modification, it’s simple and easy to understand. Once uploaded to your NodeMCU or any ESP, your device’s network port will show up in the Arduino IDE as below.

Network port on Arduino IDE

What’s next? Adding Blynk code to the OTA code.

You can see there are 2 functions at the starting of the code. This is where your main program code will be. The functions void yourSetup() and void yourLoop() will word just like the void loop() and the void setup() functions.

void yourSetup(){
  //put your code that need to run once
}

void yourLoop(){
  //put the code that needs to run continuously
}

Now we need to add the Blynk code. First we need to import the Blynk header file, then add the credentials, and then copy paste the Blynk setup and loop’s code into our setup and loop. The complete code is given below.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

#include <BlynkSimpleEsp8266.h>
char auth[] = "Your_auth_token_here";

#ifndef STASSID
#define STASSID "Your_WiFi_SSID_here"
#define STAPSK "Your_WiFi_Password_here"
#endif

const char *ssid = STASSID;
const char *password = STAPSK;

void yourSetup()
{
  Blynk.begin(auth, ssid, password);
}

void yourLoop()
{
  Blynk.run();
}

void setup()
{
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED)
  {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  ArduinoOTA.setHostname("NodeMCU");

  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH)
    {
      type = "sketch";
    }
    else
    { // U_FS
      type = "filesystem";
    }

    // NOTE: if updating FS this would be the place to unmount FS using FS.end()
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR)
    {
      Serial.println("Auth Failed");
    }
    else if (error == OTA_BEGIN_ERROR)
    {
      Serial.println("Begin Failed");
    }
    else if (error == OTA_CONNECT_ERROR)
    {
      Serial.println("Connect Failed");
    }
    else if (error == OTA_RECEIVE_ERROR)
    {
      Serial.println("Receive Failed");
    }
    else if (error == OTA_END_ERROR)
    {
      Serial.println("End Failed");
    }
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  yourSetup();
}

void loop()
{
  ArduinoOTA.handle();
  yourLoop();
}

That’s it, you now have your Blynk code running on your edge device with OTA – Over The Air updates capability. Add or remove or manipulate the code in the yourSetup and the yourLoop part, you will have your OTA capability.

Having problem uploading the code? check out the FAQs

My network port is not showing up on the Arduino IDE

The Arduino IDE does have a problem detecting and working with the network ports. If your code is uploaded and the device is connected to WiFi and the network port is not being shown, restart your IDE.

If the port is not being shown even after restarting, I suggest you to shift over to PlatformIO on Visual Studio Code for micro controller programming. It has a lot better coding and debugging experience. Or check out this post if you want to setup your own custom Blynk server.

Blynk OTA

The most simple, easy to use and 100% working OTA code for Blynk with NodeMCU, ESP8266, ESP32 and so on.

Operating System: Windows 10, Linux, Mac OS, OSX

Application Category: IoT, Arduino

]]>
2217
PlatformIO for Arduino, ESP8266, ESP32 & more with VSCode | Coding super simplified https://fazals.ddns.net/platformio-arduino-with-vscode/ Thu, 18 Jun 2020 17:04:54 +0000 https://fazals.ddns.net/?p=2189 PlatformIO for Arduino, ESP8266, ESP32 & more with VSCode | Coding super simplified Read More »

]]>
The Arduino IDE is a wonderful tool to program your Arduino Boards, the ESPs as well as a few ARM micro-controller boards. It allows you to write your code and upload it to your micro controllers.

But if you have ever used or seen someone using VSCode or the Visual Studio Code from Microsoft. I can assure you that, you would never ever want to use Arduino IDE ever again. PlatformIO with VS Code is a perfect combination for programming your micro controller boards, be it Arduino UNO, Arduino Mega, NodeMCU, or the ESPs.

Downloading and setting up Visual Studio Code

Step 1:

In order to use VSCode for programming your micro controller boards, you need to install the Platform IO Extension for VSCode.
So first of all you need to download Visual Studio Code from it official website. It’s a free and open source software and I personally use it for every program I code. Be it Python, HTML, CSS, C, or the Lua Script. So step 1 is to download VS Code, and then install it. There are different version available for Linux, Windows and Mac.

Step 2:

So now, that you are done downloading and install VS Code. You need to install the Platform IO extension for VS Code.

Procedure to install and enable Platform IO in VS Code for Arduino

1. Open up the Visual Studio Code Application

As soon as the installation is done. Open the Visual Studio Code application. The VS Code can not only be used for Arduino, but also for Python, HTML, CSS, JS, Java, and what ever programming language there is.

2. Navigate to the “Extensions” menu in the side bar on the left and search for PlatformIO

Open the Extensions menu from the side bar, or use the shortcut “Ctrl+Shift+x”. Next you will need to search for “PlatformIO” in the search box and click on the tiny install button.

Just wait for a few minutes for the PlatformIO extension to install and then restart the VS Code application. Now, you are ready to use it to program your micro controllers.

Importing Libraries and Boards

Remember, you had to manually add 3rd party boards like the NodeMCUs or ESPs in the Arduino IDE from the preferences settings in the IDE. Well, you no more need to do that unnecessary thing.

We will use the basic Arduino UNO to show you how to get things done. We will make a simple LED blinking project.

Step 1:

After your PlatformIO extension is installed, you should be able to see an Alien icon just below the extensions icon in the left sidebar. Clicking on it should take you to the PlatfromIO Home in VS Code.
Click on the New Project button, a new window will appear.

Step 2:

Fill in the Name of your project.
Select the Board from the list of boards.
And then click Finish.
It usually takes a few minutes to download the essentials for that particular board and then you are good to go.

In the Arduino IDE your code was saved in files with and .ino extension. But in here, it will be saved as .cpp. Yeah, thats the file extension for C++. Don’t worry, you need not learn C++ for this. All the syntax and coding style remains same as in the Arduino IDE. But there are a few tiny changes to be made.

Understands file structure in VS Code.

First of all, lets have a look at the files in our project.

As it can be seen, there are a number of files in project UNO’s workspace.
The main file that contains all of your code is the main.cpp file.
Another file of importance is the last file platformio.ini. This file is used for configuring all the various parameters for communicating with the board, for example the baud rate. Well will cover that later.

Now, click on the file main.cpp and you should see a few lines of code already written for you. Just like in the Arduino IDE.

#include <Arduino.h>

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

You can see that there is a new line in the code, just before your void setup().

#include <Arduino.h>

This is all the difference in the code you write in the Arduino IDE and the PlatformIO IDE. Just write the code to blink the onboard LED, or use the one below, and then click on the upload button at the bottom of the application. And that should work like a charm.👌

#include <Arduino.h>
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

Hope you learnt something new. Would you also like to know what’s Blynk and how to use it? Or may be learn how to setup your own website for free.

See you around 😎 Do care to share and comment.

]]>
2189
Timers | Toggling in 8051 every 1 second using timer delay https://fazals.ddns.net/toggle-a-pin-in-8051-every-1-second-using-timers/ Tue, 19 May 2020 17:48:04 +0000 https://fazals.ddns.net/?p=1322 The 8051 or the AT89C51 is an 8-bit microcontroller. The 8051 microcontroller was designed long ago by Intel. It has a 40 pin DIP – Dual Inline Package. It has 4 kilobytes of ROM, 128 bytes of ram, two internal timers, and 5 interrupts. Namely, INT0, TF0, INT1, TF1 and RI/TI. The order of priority is same as the order they are written. It also has 1 non-maskable interrupt – RESET.

There are 2 timers available in the 8051. The timer0 and the timer1, and there are 4 modes in which both of these timers can be configured. And each of it can be configured as a Timer or as a Counter.

Difference between timers and counters

Timer in 8051 is used to provide timing or delays between two events in the controller. Whereas, a counter is used to count the number of events. The TMOD or the Timer MOD register, which is a byte addressable register, is used to configure the timer/counter.
Consider the TMOD register as shown below. The 0th and the 1st bit is used to configure the modes for timer0, and the 4th and 5th bit for timer1.
The 2nd and the 6th bit is used for configuring it in either timer mode or counter mode for timer0 and timer1 respectively. If the 2nd/6th bit is 0, its configured as timer, else it’s in counter mode.

The TMOD Register in 8051
  1. Gate: The gate bit decides whether the timer is controlled – RUN or STOP, with the internal interrupts, TR0 and TR1 or the external ones – INT0 & INT1.
  2. C/T: This bit decides whether to operate in timer mode or in counter mode
  3. M0, M1: These bits decides the mode of operation of the timers.

Timer modes in 8051

There are 4 timer modes in the 8051 microcontroller.

  • Mode 0
    Mode 0 is a 13-bit timer/counter. All the 8 bits from the upper byte are used with 5 most significant bit from the lower byte. Timer in this mode can be used by status check method. Maximum delay in this mode is 8.8 millisecond at a crystal frequency of 11.0592 MHz.
  • Mode 1
    When using mode 1, the timer/counter is configured in 16-bit mode. To be specific, it’s counts all the way from 0x0000 to 0xffff. And this mode gives a maximum delay of 71.106 millisecond, again at a crystal frequency of 11.0592 MHz.
  • Mode 2
    In mode 2 configuration, the timer/counter works in 8 bit mode but has a special feature this time. It has auto reload capacity. Meaning that, it can run continuously, all on its own, reloading the timer with the value stored in the higher byte. This mode is usually used for setting the baud rate for serial communication.
  • Mode 3
    Mode 3 is a split mode where in the timer or counter operates in the 8-bit mode. The TL0 uses the timer flag TF0, where as the TH0 uses the timer flag TF1. Yes, its timer0 using flags of both timer0 and timer1.

The concept of delays and timers

Now that you know the basic working of the timers in the 8051 microcontroller, let’s go through the concept of delays.
Delays are nothing but the cycles of operation with in the controller where the controller does nothing, literally nothing. If you know any programming language, its similar to a for or while loop that does nothing.

The most common clock frequency in the 8051 is 11.0592 MHz. The main reason to use this frequency is it compatibility with the most common baud rates in serial communication. Now, this clock frequency will give us a machine cycle time period of 1.085 microsecond. For a delay of 1 second, we need 921600 machine cycles.

We will be using timer0 in mode 1 configuration. Since it’s a 16-bit timer the maximum delay will be 71.11 millisecond. So, we need to run the timer for 14 complete cycles + 4096 machine cycles. I’ll leave the calculations to you.

So, now that we are done with the theory. Let’s have a look at the code.

The Assembly Code

				org 0000h
					mov p1, #00h
					mov tmod, #01h
loop:				cpl p1.5    ;compliment pin 1.5
					acall delay
					acall smallDelay
					sjmp loop

;the subroutine delay is to loop for 14 complete 16-bit timer cycles
;and the subroutine smallDelay is for looing for 4096 times.
;the rest of the code is self explainatory. 					
					
delay:				mov r0, #14
					mov tl0, #00h
					mov th0, #00h
					setb tr0
timerLoop:			jnb tf0, timerLoop
					clr tf0
					djnz r0, timerLoop
					clr tr0
					ret

smallDelay:			mov tl0, #00h
					mov th0, #0f0h
					setb tr0
timerLoop2:			jnb tf0, timerLoop2
					clr tr0
					clr tf0
					ret
					
					end

Download the code from here.
This code will result in toggling of pin 1.5 every second, only if operating at 11.0592 MHz. The C-equivalent code for the same program is also geven.

The embedded C Code | 8051 timer programming in C

#include<reg51.h>

sbit pin = P1^5;

void delay(){
    int i;
    TMOD = 0x01;
    for(i=0; i<1000; i++){
				TH0 = 0xFC;
				TL0 = 0x66;
				TR0 = 1;
        while(TF0 != 1){
            ;
        }
				TR0 = 0;
        TF0 = 0;
    }
}

void main(){
    while (1)
    {
        pin = ~pin;
        delay();
    }
    
}

Download this code from my Github.
That completes the part of toggling any pin with a delay of exactly 1 second.

Read more posts on 8051 from here.

FAQs

How do I change the pin that has to be toggled?

You can do that by simply changing the line cpl p1.5 or the line sbit pin = P1^5; in embedded C to the required pin. You can also modify the code to toggle an entire port instead of a single pin.

What’s the difference between a Timer and a Counter?

I suggest you read this again.

How do I change the time for toggling?

Simply change the delay function, by changing the value in the TH0 and TL0.

What are the different timer/counter modes in 8051

]]>
1322
Latest Spectrum Analyser using Python | Part-2 https://fazals.ddns.net/spectrum-analyser-part-2/ Mon, 11 May 2020 01:31:12 +0000 https://fazals.ddns.net/?p=1002 Latest Spectrum Analyser using Python | Part-2 Read More »

]]>

Since we have already built spectrum analyser in part 1, where we use the PyAudio Python library to open the microphone and bring in raw binary data into the code. Convert that binary data into 16-bit integers and displayed them on a Plot using the MatPlotLib’s PyPlot.
If you have not built it in the part one, click here and build the part 1 as this part will be a continuation to that.

The algorithm to calculate the Spectrum

We will be using the FFT or the Fast Fourier Transform to calculate spectrum for the spectrum analyser. Now, FFT is an algorithm that computes the Discrete Fourier Transform. In short the DFT of a sequence of signal to represent it in frequency domain.
There are many different FFT algorithms based on a wide range of published theories, from simple complex-number arithmetic to group theory and number theory. The one we will be using is the python fft algorithm from the library Numpy.

Package 📦 to import for fft in Python?

As far as the the part of the code which calculates the FFT of a sequence, there are many libraries that offer simple classes to do so. Since we already imported Numpy. And since it already provides the class or method to calculate the FFT. We will not be importing any new library.

Also, take a note that there are other libraries available that compute the FFT of a sequence of signal.

The code for audio spectrum analyser / audio visualizer

Since we have already coded in the first part, we will only be making a few changes to the code, a few additions and then we will be good to go. If you don’t have the code get it from here.

Now in the part where we initiallise the plot objects, that is to say the figure and the axises, make the following changes.

Instead of

fig, ax = plt.subplots()

make it

fig, (ax,ax1) = plt.subplots(2)

and add the following lines, to the code. The first line creates a one dimentional array containing the values from 0 uptill 44100 with number of parts equal to the size of CHUNK. And the next line sets the X axis as semilog since the frequency representation is always done on semilog plots.

x_fft = np.linspace(0, RATE, CHUNK)
line_fft, = ax1.semilogx(x_fft, np.random.rand(CHUNK), 'b')

Since the output of the FFT computations are going to range from 0 to 1. We change the Y limits of the frequency plot. And also, since the computation produces a mirror of the spectrum after half the sampling rate. We dont need the part after half the sampling rate, that is after 22050. And hence we change the X limit also.

ax1.set_xlim(20,RATE/2)
ax1.set_ylim(0,1)

And then in the infinite loop, add the following lines to compute the FFT and plot it.
Since the computed FFT contains both the real and the imaginary part. We take the absolute value of the returned FFT spectrum, multiply it by 2, and then divide it by 33000 times CHUNK to produce a plot with Y values ranging from 0 to 1.

line_fft.set_ydata(np.abs(np.fft.fft(dataInt))*2/(33000*CHUNK))

The Complete code

import numpy as np #importing Numpy with an alias np
import pyaudio as pa 
import struct 
import matplotlib.pyplot as plt 

CHUNK = 1024 * 1
FORMAT = pa.paInt16
CHANNELS = 1
RATE = 44100 # in Hz

p = pa.PyAudio()

stream = p.open(
    format = FORMAT,
    channels = CHANNELS,
    rate = RATE,
    input=True,
    output=True,
    frames_per_buffer=CHUNK
)



fig, (ax,ax1) = plt.subplots(2)
x_fft = np.linspace(0, RATE, CHUNK)
x = np.arange(0,2*CHUNK,2)
line, = ax.plot(x, np.random.rand(CHUNK),'r')
line_fft, = ax1.semilogx(x_fft, np.random.rand(CHUNK), 'b')
ax.set_ylim(-32000,32000)
ax.ser_xlim = (0,CHUNK)
ax1.set_xlim(20,RATE/2)
ax1.set_ylim(0,1)
fig.show()

while 1:
    data = stream.read(CHUNK)
    dataInt = struct.unpack(str(CHUNK) + 'h', data)
    line.set_ydata(dataInt)
    line_fft.set_ydata(np.abs(np.fft.fft(dataInt))*2/(11000*CHUNK))
    fig.canvas.draw()
    fig.canvas.flush_events()

Then, when you run the program, you should be able to see the time domain as well as the frequency domain representation of the sequence from the microphone.

Spectrum Analyser

You shoud be able to get plots similar to one given above. Use this website to generate pure sine/square/triangular waves with any frequency you want to test out this project.

Liked the project? Drop your reviews in the comment section, and share it among your fellow mates. 👍🏻
Check out my other posts.
Follow me on Social Media 👇👇👇

]]>
1002
Realtime Spectrum Analyser using Python | Part-1 https://fazals.ddns.net/spectrum-analyser-part-1/ Sat, 09 May 2020 08:11:12 +0000 https://fazals.ddns.net/?p=865 Realtime Spectrum Analyser using Python | Part-1 Read More »

]]>

A Spectrum Analyser measures the amplitude or the magnitude of the input signal, with respect to the frequency. Its mainly used to analyse the amplitude of signals at different frequencies.

Python is a high level interpreted, multipurpose programming language. If you ever wanted to build your own audio spectrum analyser, that works out of the box with your microphone in Windows, linux or Mac, you are at the right place.

A realtime spectrum analyser doesn’t have any build time or lag. The analyser is able to sample the incoming spectrum in the time domain and convert the sampled information into frequency domain.

The algorithm that we will be using to convert the time domain signal to frequency domain is called FFT. Briefly, fast fourier transform. The Numpy’s fft library for Python is used to generate the fft for the python spectrum analyser or the python audio audio visualizer.

Libraries Required for python spectrum analyser / audio visualizer

For the first part of the video, where we sample the audio from the microphone and display it in the time domain. We will be needing the following Python Libraries.

  1. Numpy
    Numpy is a Python Library that adds support for large, multi-dimentional arrays and matrices. It has high level mathematical functions to operate on the data.
  2. PyAudio
    PyAudio is another Python Library that can be easily used to play and record audio with Python on a variety of platforms.
  3. Struct
    Struct is another Python module that performs conversion between Python values and C structures. It basically performes conversion of data from binaries to their equivalent python data types.
  4. MatPlotLib
    Matplotlib is a library for the Python and its numerical mathematics extension NumPy. It provides an object-oriented API for embedding plots into applications using general-purpose GUI toolkits like Tkinter, wxPython, Qt, or GTK+.

Installing Libraries

Installing the required libraries is very simple.
To install Numpy, run the following command in CLI

pip install numpy

Installing MatPlotLib and PyAudio is done in the same way.

pip install PyAudio
pip install matplotlib

If you face any problem installing PyAudio, download the .whl file based on your Python version and system architecture from here, and then run the command

pip install /path_to_whl_file/filename.whl

The Struct module comes pre-installed with Python.

The code

As always in Python we start off with importing the required libraries.

Skip the explination and jump to the complete code.

import numpy as np
import pyaudio as pa 
import struct 
import matplotlib.pyplot as plt 

Then, we initialize some variables.
CHUNK is the number of samples that will be processed and displayed at any instance of time.
FORMAT is the data type that the PyAudio library will output.
CHANNELS is the number of channels our microphone has.
RATE is the sampling rate. We will chose the most common one, that is 44100Hz or 44.1KHz.

CHUNK = 1024 * 2
FORMAT = pa.paInt16
CHANNELS = 1
RATE = 44100 # in Hz

Next we create a PyAudio object from class PyAudio and store it in a variable p.

p = pa.PyAudio()

Then, we use the open method on the object p and pass on the variables we initialiszed as parameters.

stream = p.open(
    format = FORMAT,
    channels = CHANNELS,
    rate = RATE,
    input=True,
    output=True,
    frames_per_buffer=CHUNK
)

Now, we will initiallise the plot with random values and set the limits for each of the two axises.

fig,ax = plt.subplots()
x = np.arange(0,2*CHUNK,2)
line, = ax.plot(x, np.random.rand(CHUNK),'r')
ax.set_ylim(-32770,32770)
ax.ser_xlim = (0,CHUNK)
fig.show()

Finally, we create an infinite loop and read the data from the microphone, convert the data into 16-bit numbers and further plot it using the matplotlib.pyplot function.

while 1:
    data = stream.read(CHUNK)
    dataInt = struct.unpack(str(CHUNK) + 'h', data)
    line.set_ydata(dataInt)
    fig.canvas.draw()
    fig.canvas.flush_events()

Now when you run the code. You should be able to see the program running flawlessly. If you encounter any error, check the default input device in your sound settings.

The complete code

import numpy as np 
import pyaudio as pa 
import struct 
import matplotlib.pyplot as plt 

CHUNK = 1024 * 2
FORMAT = pa.paInt16
CHANNELS = 1
RATE = 44100 # in Hz

p = pa.PyAudio()

stream = p.open(
    format = FORMAT,
    channels = CHANNELS,
    rate = RATE,
    input=True,
    output=True,
    frames_per_buffer=CHUNK
)



fig,ax = plt.subplots()
x = np.arange(0,2*CHUNK,2)
line, = ax.plot(x, np.random.rand(CHUNK),'r')
ax.set_ylim(-60000,60000)
ax.ser_xlim = (0,CHUNK)
fig.show()

while 1:
    data = stream.read(CHUNK)
    dataInt = struct.unpack(str(CHUNK) + 'h', data)
    line.set_ydata(dataInt)
    fig.canvas.draw()
    fig.canvas.flush_events()

This completes the part one. Feel free to comment and discuss.
Want to learn how to create and setup your own Blynk server to get started with IoT ?
Or want to know how I created this website? Do care to give a thumbs up and share.😄

]]>
865