Posted on Leave a comment

3 Step to use External Interrupt on ESP8266

I was in the middle of replicating my 433 MHz remote control using Arduino. The receiver circuit is quite simple and it is using Arduino pin 2 (interrupt) to detect the data signal from the receiver.

I was wondering whether I can do the same thing with ESP8266. After a short google, I found some information about Interrupt pin D3 (GPIO0) and also D0 (GPIO16). At a glance it seems do able.

Here are the steps to use the interrupt.

  1. Initialise IO pin as input
  2. Initialise IO with Interrupt Subroutine definition
  3. Interrupt Subroutine.

Here are the code that I stumble upon from the Circuits4you.com website.

const int interruptPin = 0; //GPIO 0 (Flash Button) STEP 1
const int LED=2; //On board blue LED
 
void setup() {
  Serial.begin(115200);
  pinMode(LED,OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, CHANGE); // STEP 2
}
 
void loop()
{
    digitalWrite(LED,HIGH); //LED off
    delay(1000);
    digitalWrite(LED,LOW); //LED on
    delay(1000);
}
 
//This program get executed when interrupt is occurs i.e.change of input state - STEP 3
void handleInterrupt() {
    Serial.println("Interrupt Detected");
}

I will try this tonight and report back whether the Interrupt detection works or not.

The Remote.

BAUHN Remote Control

The remote consist of 4 ON button and 4 OFF buttons, each one is labelled A, B, C and D.It works independently controlling the remote power point switch.

The power point needs to be sync against one of the button pair (A, B, C or D). In this experiment I am detecting button B.

Below are the connection between ESP8266 to the 433 MHz receiver. As you can see I only connected 3 cables. 3.3V Vcc for Power (red cable), GND (green cable) and Data (Yellow) connected to GPIO0 of ESP8266 (D3).

I had used a slightly different sketch which is utilising the rc-switch library, and it also can provide the same detection that I had done using Arduino Uno. Here are the sketch that I had used to detect the remote.

#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();

void setup() {
Serial.begin(9600);
mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin GPIO0 or D3 in ESP8266

pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if (mySwitch.available()) {
Serial.print("Received ");
output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol());
mySwitch.resetAvailable();
}
}

I had connect the receiver to Pin D3 on ESP8266, and getting the following result when I press the B-ON button.

Received Decimal: 9085236 (24Bit) Binary: 100010101010000100110100 Tri-State: not applicable PulseLength: 500 microseconds Protocol: 5
Raw data: 7036,1061,455,589,934,607,918,613,952,1071,454,575,955,1065,457,565,971,1033,509,509,1021,1022,506,526,995,542,981,548,977,543,979,1055,482,561,1057,466,1080,942,548,980,540,486,1067,956,552,484,1071,564,966,
Received Decimal: 9085236 (24Bit) Binary: 100010101010000100110100 Tri-State: not applicable PulseLength: 500 microseconds Protocol: 5
Raw data: 6969,1116,407,629,907,553,987,554,928,1085,445,593,924,1123,405,623,912,1122,403,625,901,1049,489,537,988,546,974,556,965,565,970,1045,483,561,944,559,969,1070,453,1073,453,578,949,1066,460,577,946,545,1021,

So I can conclude that the Interrupt definitely working ok. The next step would be to capture a few more data and trying to send it back via the 433MHz transmitter to try to replicate each of the button. Given that the ESP8266 can be connected to WIFI and also can server as a webserver this will make it possible to control the remote via internet as an IoT device.

Stay tune for the next article. Please share or subscribe if you like to see more of this article and feel free to drop me a comment.

Posted on Leave a comment

Connecting IoT Sensors data to Node-RED

This is the continuation of the Temperature sensor project in the previous post. The concept is to allow the data from sensors (temperature, motion) can be displayed in Apple Homekit, so that the user can interact with the information and control the IoT connected devices (Lights, Fan, etc). It is best described in the following picture.

The following instruction shows how to install Node-RED on a linux computer running Debian OS.

sudo npm install -g --unsafe-perm node-red

You will also need to install the mosquitto MQTT message broker, here are the command required

sudo apt-key add mosquitto-repo.gpg.key
sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list
sudo apt-get update
sudo apt-get install mosquitto

You will also need the latest Python library, so grab them using the following instruction

sudo apt-get install python-dev

Test the installation. In this example I was using Linux Debian, so typing the command node if you get the following in the command prompt, that means the installation is successful. So then you can exit node by typing .exit command in the prompt >.

If all goes well, you can run the node-red command in the command prompt. You should get the following message. This shows that the node-red is now running at http://127.0.0.1:1880.

Node-RED Settings

Node-RED setting file called settings.js, on Linux it is located in the /usr/lib/node-modules/node-red folder. You will have another settings.js file in the .node-red folder in your home folder. This setting will be loaded by default.

Creating the flow in Node-RED

Now that you have a running Node-RED, it is time to create the flow. In this example we will create a simple flow to read temperature posted by our ESP8266. Let’s start by firing up your favourite browser and point to the following URL: http://127.0.0.1:1880/

You will be presented with a blank screen similar to the following picture. Now to start creating a flow, drop an “Inject” node from input section. We will use this as a trigger to get the temperature reading. Once you dropped it in, double click to set the property. We call the node “timestamp” and we set the interval to repeat every 4 minutes.

The next step is to connect this with an “http” node, so drop an “http” node and configure this as http GET to call a server side script in the webserver. What the script needs to return is the temperature in JSON format as below:

{"CurrentTemperature":25}

So my data_store2.php script does exactly that, as shown in the following code:

 /* readtemperature file from temp.txt file    return the value back in JSON format for HomeKit  */ 
$theparam = $_GET;
$file = './temp.txt';
$temperature = file_get_contents($file);
echo '{"CurrentTemperature":'.$temperature.'}';

Now the final step is to connect to the “Homekit” node from the Advance nodes menu. Once you drop the “Homekit” node, you can double click to configure the property as below.

Once all had been connected, it is time to deploy the node. You can do this by clicking on the “Deploy” button at the top of the Node-RED window. You will need to click the “Deploy” button whenever you make any changes to the node. Sometime the deployment might stop the Node-RED server, so you just have to run the node-red command again in the command prompt.

If all goes well, you can now test this node by clicking on the button next to “timestamp” node, the temperature should be read from the webserver and displayed in Homekit, similar to the following picture.

That conclude this session on how to configure the Node-RED to work with our temperature sensor data from ESP8266. Please let me know if you have any questions related to this and don’t forget to subscribe for update on the similar projects. The next session we are going to connect this to the Apple homekit in IPhone or IPad.

Posted on Leave a comment

Download Microsoft Sharepoint List Attachments using Powershell script

I stumble across a problem when trying to download attachment from the Sharepoint List. The list have more than 50,000 rows, the problem with the big list is Windows explorer is not able to display the list in Explorer view, so there is a need to use the Powershell script to download all the attachment programmatically.

Step 1. Make sure you have the Sharepoint Client dll required as specified in the following code


[void][Reflection.Assembly]::LoadFrom("$env:CommonProgramFiles\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll")
[void][Reflection.Assembly]::LoadFrom("$env:CommonProgramFiles\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll")

Step 2. Define the sharepoint site and the list library

The sharepoint site and the library is defined using the following $webUrl variable and $library respectively, also don’t forget to specify the local folder where the files will be downloaded.

$webUrl = "http://website.com/sites/sharepointsite" 
$library = "SharepointLibrary"
Local Folder to dump files
$tempLocation = "C:\temp\"

Step 3. Define how many rows the CamlQuery should return on each iteration

The beauty of the PowerShell Script is that you can specify how many rows to return each time, so the script will not have a problem recursively going through a big list that are over 50,000 and being able to download all the attachment. The following code shows that we are limiting the query to return 3000 rows.

$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery $camlQuery.ViewXml ="<View> <RowLimit>3000</RowLimit></View>"

Step 4. Define the folder structure to hold all the attachment to be downloaded

The following code is using the combination of Title and ID as the folder name to store the attachment. It also check whether the folder already exists prior to creating a new one.


    $folderName=$listItem["Title"]+"_"+$listItem["ID"]
    $destinationfolder = $tempLocation + "\"+ $folderName 

     #check if folder is exist or not, if not exist then create new
  if (!(Test-Path -path $destinationfolder))        
   {            
     $dest = New-Item $destinationfolder -type directory      
     Write-Host "Created Folder with Name:" $folderName    
   }

The following is the full code to download the list attachments and put them in the local folder. The credential used is the user credential where the script is executed, that means the login user will need to have access to the SharePoint Site and able to download the attachement.


[void][Reflection.Assembly]::LoadFrom("$env:CommonProgramFiles\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll")
[void][Reflection.Assembly]::LoadFrom("$env:CommonProgramFiles\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll")
Clear-Host
#$cred = Get-Credential "user@microsoft.com"
#$credentials = New-Object Microsoft.Sharepoint.Client.SharePointOnlineCredentials($cred.Username, $cred.Password)
$webUrl = "http://website.com/sites/sharepointsite"

$clientContext = New-Object Microsoft.Sharepoint.Client.ClientContext($webUrl)
Write-Host "Connecting To Site: " $webUrl   

 $username = "$env:USERDOMAIN\$env:USERNAME"

$library = "SharepointLibrary" 
#Local Folder to dump files
$tempLocation = "C:\temp\"    

$global:web = $clientContext.Web;
$global:site = $clientContext.Site;

$clientContext.Load($web)
$clientContext.Load($site)

$listRelItems = $clientContext.Web.Lists.GetByTitle($library)

$clientContext.Load($listRelItems)
$clientContext.ExecuteQuery();
Write-Host "list item count " $listRelItems.ItemCount

$camlQuery = New-Object Microsoft.SharePoint.Client.CamlQuery
$camlQuery.ViewXml =" 3000"
 $listCollection = New-Object System.Collections.Generic.List[string] 
 $count = 0
Do {
$allItems=$listRelItems.GetItems($camlQuery)
$clientContext.Load($allItems)
$clientContext.ExecuteQuery()
$camlQuery.ListItemCollectionPosition = $allItems.ListItemCollectionPosition
foreach ($listItem in $allItems)
 {
    $folderName=$listItem["Title"]+"_"+$listItem["ID"]
    $destinationfolder = $tempLocation + "\"+ $folderName 

     #check if folder is exist or not, if not exist then create new
  if (!(Test-Path -path $destinationfolder))        
   {            
     $dest = New-Item $destinationfolder -type directory      
     Write-Host "Created Folder with Name:" $folderName    
   }
    $clientContext.load($listItem)
    $clientContext.ExecuteQuery();

    $attach = $listItem.AttachmentFiles
    $clientContext.load($attach)
    $clientContext.ExecuteQuery();
    if($attach -ne $null){
        Write-Host "No of attachment:" $attach.Count
        foreach ($attachitem in $attach){
            Write-Host "Downloading Attachements started: "   $attachitem.FileName
            $attachpath = $webUrl + "/Lists/"+ $library + "/Attachments/" + $listItem["ID"] + "/" + $attachitem.FileName
            Write-Host "path: " $attachpath 
         
            $path = $destinationfolder + "\" + $attachitem.FileName
            Write-Host "Saving to the location:"  $path

            $siteUri = [Uri]$attachpath
            $client = new-object System.Net.WebClient
            $client.UseDefaultCredentials=$true
            
            try{
                  $client.DownloadFile($attachpath, $path)
                  $client.Dispose()
            } catch{
                write-error "Failed to download $url, $_ "
            }

        }
    }else {
     Write-Host   "For above current item don't have any attachments" 
    }
  }
Write-Host " List item" $count
$count++
} while ($camlQuery.ListItemCollectionPosition -ne $null)
     Write-Host   "Script execution done !" 

Please let me know if the above script is of useful to you and don’t forget to share or subscribe for more frequent update to the similar topic. You can also drop me a line or questions if you have any.

Posted on Leave a comment

4 Steps to download Microsoft Sharepoint Document Library recursively

I stumble across this problem when we try to decommissioning Microsoft Sharepoint. We had a huge document library and it is not possible to copy them from explorer view, so the solution is to use PowerShell script to do this automagically.

Step 1. Define the DLL that is required.

This is done through the following code snippets. It is crucial to have the 2 DLL to allow the copy function to work. The script will use the credential of the user login into the machine and executing the script. This removes the complexity having to enter the sharepoint credential into the script.

# Load the SharePoint 2013 .NET Framework Client Object Model libraries. # 
[void][Reflection.Assembly]::LoadFrom("c:\Microsoft.SharePoint.Client.dll")
[void][Reflection.Assembly]::LoadFrom("c:\Microsoft.SharePoint.Client.Runtime.dll")

Step 2. Define the sharepoint site URL and the Document Library repository

You can simply enter the sharepoint URL by replacing the following $serverURL variable. Enter the document library by replacing the $DocumentLibrary variable and don’t forget to define the destination folder.

$serverURL = “http://sharepoint.url/sites/sitename”
$destination = "C:\temp\"
$DocumentLibary = "Document Library Name"

Step 3. Choose whether you only want specific folder to be downloaded from the Document Library

Change the folder name that you are interest in downloading, in the following example we are only interested in downloading folder “Payments” and all the folder underneath it.


function Parse-Lists ($Lists)
{
$clientContext.Load($Lists)
$clientContext.Load($Lists.RootFolder.Folders)
$clientContext.ExecuteQuery()
    
    foreach ($Folder in $Lists.RootFolder.Folders)
        {
            if ($Folder.name -eq "Payments"){   #onlydownload selected folder
                recurse $Folder
            }
        }

}

Step 4. Execute the script via PowerShell window or from Command line.

To execute the script via command line you can execute the following Powershell command, with the assumption the name of the powershell script is “scriptname.ps1”

C:\Powershell.exe scriptname.ps1

Here are the full script to download the Sharepoint Document library, be careful the script will download the entire document library recursively, so please make sure you check Step 3 above. With great power comes great responsibility.

# Load the SharePoint 2013 .NET Framework Client Object Model libraries. # 
[void][Reflection.Assembly]::LoadFrom("c:\Microsoft.SharePoint.Client.dll")
[void][Reflection.Assembly]::LoadFrom("c:\Microsoft.SharePoint.Client.Runtime.dll")
Clear-Host

$serverURL = “http://sharepoint.url/sites/sitename”
#$siteUrl = $serverURL+"/documents”
$destination = "C:\temp\"
$DocumentLibary = "Document Library Name"
$downloadEnabled = $true
$versionEnabled = $false

# Authenticate with the SharePoint Online site. # 
#$username = ""
#$Password = ""
#$securePassword = ConvertTo-SecureString $Password -AsPlainText -Force  

$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($serverURL) 
#$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword) 
#$clientContext.Credentials = $credentials 
if (!$clientContext.ServerObjectIsNull.Value) 
{ 
    Write-Output "Connected to SharePoint Online site: '$serverURL'"
} 


function HTTPDownloadFile($ServerFileLocation, $DownloadPath)
{
#Download the file from the version's URL, download to the $DownloadPath location
    $webclient = New-Object System.Net.WebClient
    $webclient.credentials = $credentials
    Write-Output "Download From ->'$ServerFileLocation'"
    Write-Output "Write to->'$DownloadPath'"
    $webclient.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
    $webclient.DownloadFile($ServerFileLocation,$DownloadPath)
}

function DownloadFile($theFile, $DownloadPath)
{
    $fileRef = $theFile.ServerRelativeUrl;
    Write-Host $fileRef;
    $fileInfo = [Microsoft.sharepoint.client.File]::OpenBinaryDirect($clientContext, $fileRef);
    $fileStream = [System.IO.File]::Create($DownloadPath)
    $fileInfo.Stream.CopyTo($fileStream);
    $fileStream.Close()
}

function Get-FileVersions ($file, $destinationFolder)
{
    $clientContext.Load($file.Versions)
    $clientContext.ExecuteQuery()
    foreach($version in $file.Versions)
    {
        #Add version label to file in format: [Filename]_v[version#].[extension]
        $filesplit = $file.Name.split(".") 
        $fullname = $filesplit[0] 
        $fileext = $filesplit[1] 
        $FullFileName = $fullname+"_v"+$version.VersionLabel+"."+$fileext           

        #Can't create an SPFile object from historical versions, but CAN download via HTTP
        #Create the full File URL using the Website URL and version's URL
        $ServerFileLocation = $siteUrl+"/"+$version.Url

        #Full Download path including filename
        $DownloadPath = $destinationfolder+"\"+$FullFileName
        
        if($downloadenabled) {HTTPDownloadFile "$ServerFileLocation" "$DownloadPath"}

    }
}

function Get-FolderFiles ($Folder)
{
    $clientContext.Load($Folder.Files)
    $clientContext.ExecuteQuery()

    foreach ($file in $Folder.Files)
        {

            $folderName = $Folder.ServerRelativeURL
            $folderName = $folderName -replace "/","\"
            $folderName = $destination + $folderName
            $fileName = $file.name
            $fileURL = $file.ServerRelativeUrl
            
                
            if (!(Test-Path -path $folderName))
            {
                $dest = New-Item $folderName -type directory 
            }
                
            Write-Output "Destination -> '$folderName'\'$filename'"

            #Create the full File URL using the Website URL and version's URL
            $ServerFileLocation = $serverUrl+$file.ServerRelativeUrl

            #Full Download path including filename
            $DownloadPath = $folderName + "\" + $file.Name
                    
            #if($downloadEnabled) {HTTPDownloadFile "$ServerFileLocation" "$DownloadPath"}
            if($downloadEnabled) {DownloadFile $file "$DownloadPath"}

            if($versionEnabled) {Get-FileVersions $file $folderName}
            
    }
}


function Recurse($Folder) 
{
       
    $folderName = $Folder.Name
    $folderItemCount = $folder.ItemCount

    Write-Output "List Name ->'$folderName'"
    Write-Output "Number of List Items->'$folderItemCount'"

    if($Folder.name -ne "Forms")
        {
            #Write-Host $Folder.Name
            Get-FolderFiles $Folder
        }
 
    Write-Output $folder.ServerRelativeUrl
 
    $thisFolder = $clientContext.Web.GetFolderByServerRelativeUrl($folder.ServerRelativeUrl)
    $clientContext.Load($thisFolder)
    $clientContext.Load($thisFolder.Folders)
    $clientContext.ExecuteQuery()
            
    foreach($subfolder in $thisFolder.Folders)
        {
            Recurse $subfolder  
        }       
}


function Parse-Lists ($Lists)
{
$clientContext.Load($Lists)
$clientContext.Load($Lists.RootFolder.Folders)
$clientContext.ExecuteQuery()
    
    foreach ($Folder in $Lists.RootFolder.Folders)
        {
            if ($Folder.name -eq "Payments"){   #onlydownload selected folder
                recurse $Folder
            }
        }

}

$rootWeb = $clientContext.Web
$LibLists = $rootWeb.lists.getByTitle($DocumentLibary)
$clientContext.Load($rootWeb)
$clientContext.load($LibLists)
$clientContext.ExecuteQuery()

Parse-Lists $LibLists

 

Please let me know if the above script is useful, feel free to subscribe to my blog, share this script or ask me any questions related to the script.

Posted on Leave a comment

Realtime Clock with 18F2550

I am trying to make use of the previous circuit on connecting LED display to 18F2550, and combining this with Real time clock module DS3231. So here are the diagram of the connection:

Here are the list of parts used in this project:

  • 18F2550 USB development board
  • Realtime clock DS3231
  • Button cell battery CR2032 (for realtime clock)
  • LCD Display
  • 10K ohm variable resistor (to control the brightness of LCD display)
  • 200 ohm pull up resistor

The 18F2550 USB development board can be shown below:

This board comes loaded with boot loader to allow easy loading of the firmware code. I am using the MPLAB IDE v8.92 to compile and build the code for the USB development board.

I am also using the previously ported LCD display code to use in this project.

Connect Everything together

First we connect the LCD Display to the Development board. We are only using 4 bit for the data transfer so here are the detail connection of the LCD Display:

  • RS LCD —- C6 Dev Board
  • EN LCD —- C7 Dev Board
  • D4 LCD —- A0 Dev Board
  • D5 LCD —- A1 Dev Board
  • D6 LCD —- A2 Dev Board
  • D7 LCD —- A3 Dev Board

You will also need to connect a pull up resistor to Anode pin of LCD display before connecting to +5V and Middle of 10k resistor to VO pin of LCD display, while the other ends of the 10K resistor is connected to VCC and GND respectively.

Test the LCD connection.

Once you had connected the LCD Display to 18F2550 development board you can load the demo display program. To load the demo program (C18-BOLT-LCD-MESSAGE-SCROLLING.HEX), you can use the loader program “MiEUSBHIDLoader.exe“. This program will display a scrolling Alphabet in the first row and numbers on the second row of the LCD Display, please make sure that this is working properly prior to continuing to the next step.

Connecting the Real time clock

First connect the button cell CR2032 to the realtime clock module DS3231. Then connect the DS3231 to the USB development board. To connect the real time clock DS3231 to the 18F2550 USB Development board use the following connection:

  • SDA RTC —- B0 Dev Board
  • SCL RTC —- B1 Dev Board

You will also need to connect the VCC of DS3231 to the 5V and GND to the ground of the 18F2550 Development board. Once this is done you can now upload the RTC clock program. You might want to recompile the code to set the date and time the first time you are loading the code

// uncomment the following to set the date and time
DS3231_SetDate(29,03,19); // setting the date to 29-Mar-2019
DS3231_SetTime(00,19,01); // setting the time to 00:19:01

Once the code is loaded, the date and time is now saved in the DS3231 module. As long as the button cell CR2032 is connected to the DS3231 module, the date and time will be retained. Now you need to recompile the code again with the above code uncommented, this is to ensure that every time you reset the USB development board, it will not reset the date and time of RTC module back to the date time above.

Please drop me a line and share this post if you like it, and let me know what I can improve on. Stay tune for the next revision that will include buttons to set the date and time.

Posted on Leave a comment

Connecting ESP8266 to P10 Display and displaying data from webserver

The concept is to have the ESP8266 driving the P10 display by reading the data from the webserver, this will ensure that the data can be updated automatically in the webserver via some automation and the P10 is being set to poll the data periodically and displaying it on the P10 display. You can see the concept in the following diagram:

Here are the connection diagram to connect to ESP8266 to P10 Display.

Connections

For simplicity here are the connection required from ESP8266 to the P10 header.

Coding preparation

What you will need is the Arduino IDE interface and loaded with the following library:

  1. DMD2 library can be downloaded via the link
  2. SPI library (this is usually already installed with Arduino)
  3. ESP8266WiFi library (you can search for this in the Arduino library via Sketch->Include Library->Manage Library and put ESP8266 in the search box)

The first step is to connect the ESP8266 to your WIFI, this is done in the following code

char ssid[] = "ssid"; //  your network SSID (name)
char pass[] = "password"; // your network password (use for WPA, or use as key for WEP)
...
void setup() {
...
WiFi.begin(ssid, pass);
...
}

Then assuming the data is located in the webserver path /arduino/message.json, we then need to initialise the location as below:

const char* webserver = "webserver.com";      // webserver where the cloud is hosted
String messagePath = "/arduino/message.json"; // location of message data

Once the connection to webserver is established, the following function will parse the data and store in the local variable MESSAGE:

void readMessage(){
DebugLn("readMessage");
DebugLn("Connecting to " + String(webserver));
WiFiClient client;
const int httpPort = 80;
if (!client.connect(webserver, httpPort)) {
Serial.println("connection failed");
return;
}
client.print(String("GET ") + messagePath + " HTTP/1.1\r\n" +
"Host: " + webserver + "\r\n" +
"Connection: keep-alive\r\n\r\n");
delay(500); // wait for server to respond
// read response
String section="header";
while(client.available()){
String line = client.readStringUntil('\r');
// Serial.print(line);
// we’ll parse the HTML body here
if (section=="header") { // headers..
Serial.print(".");
if (line=="\n") { // skips the empty space at the beginning
section="json";
}
}
else if (section=="json") { // print the good stuff
section="ignore";
String result = line.substring(1);
// Parse JSON
int size = result.length() + 1;
char json[size];
result.toCharArray(json, size);
StaticJsonBuffer<200> jsonBuffer;
JsonObject& json_parsed = jsonBuffer.parseObject(json);
if (!json_parsed.success())
{
Serial.println("parseObject() failed");
return;
}
// read the message
MESSAGE = json_parsed["message"];
Serial.println(MESSAGE); //display message in serial window
}
}
Serial.print("closing connection. ");
}

The last piece is to display the message to the screen with the following function:

void scrolling() {
const char next = MESSAGE; while (next) {
dmd.clearScreen();// clear screen
if (i != 0) {
box.print(*next); //print the led pannel
}
i++;
delay(800); // letters speed changing
next++;
}
}

The full source code can be downloaded via the following link.

Please don’t hesitate to let me know if you experience any issue with the code. You can buy me a coffee later if you like this post.

Posted on Leave a comment

Adding Piezzo speaker to Analog Output

In my previous post, I was using my LED matrix circuit to display the Fibonacci clock. So I am a bit stretched on the I/O port. And my son asked me, whether I can add a buzzer to beep every 10 seconds so that he can do “plank” exercise. So I found my old Piezzo speaker.

Piezzo Speaker

Because I am running out of port, I am trying to use the Digital Pin 1. Pin one is labelled as TX, so the speaker beeps every second the clock updates. It also makes noise when you loaded the code to Arduino. What I had done is just combining the code from Mario speaker song to play when the button is being pressed on the Fibonacci clock.

It doesn’t work well when I am connecting the piezzo speaker to Digital pin 1. So I go on researching whether I can connect the speaker to Analog pin. Apparently you can program the Analog pin to behave like a digital pin.

Here are the initialisation code:

const int speakerPinMelody =  A0;   // using Analog pin A0 as output

void setup() {
...
pinMode(speakerPinMelody, OUTPUT); // to initialise the analog output
...
}

Once the initialisation is done, I can use the same code to play the melody as used in the Super Mario speaker song circuit.

void playSong(int theSong[], int theTempo[], int arraySize) {
// iterate over the notes of the melody:
int totalNotes = arraySize;
Serial.println("Total note:" + String(totalNotes));
for (int thisNote = 0; thisNote < totalNotes; thisNote++) {

// to calculate the note duration, take one second divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000 / theTempo[thisNote];
tone(speakerPinMelody, theSong[thisNote], noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
Serial.println("Delay:" + String(pauseBetweenNotes));
delay(pauseBetweenNotes);
Serial.println("Stop");
// stop the tone playing:
noTone(speakerPinMelody);
}

delay(10);
Serial.println("Final Delay");
}

I am using a 1K resistor to connect one end of the piezzo speaker (red wire) to pin A0 and the other end of the speaker (black wire) is connected to the GND.

I omitted the rest of the LED Matrix circuit for simplicity. When the button is pressed the circuit will display a random dice face (1-6) on the LED matrix and then it will play the Super Mario song.

The result can be seen in the following youtube video. I hope you enjoy this post. Please leave a comment if you like this post or subscribe for frequent update on more simple circuits with Arduino. You can also send me an email if you would like the full source code.

Posted on Leave a comment

UniFi network controller failed to start

I was helping a friend to fix his UniFi network controller that failed to start. I didn’t know much about it, and we think this is related to the database mongodb which is full with logs of the events which make the size bloated up.

Here are the steps that I did to fix it.

  1. Stop the Unifi Service using the following command
service unifi stop

2. Repair the database with the following command

mongod --dbpath /usr/lib/unifi/data/db --smallfiles --logpath /usr/lib/unifi/logs/server.log --repair

3. Download the pruning script using WGET

wget https://ubnt.zendesk.com/hc/article_attachments/115024095828/mongo_prune_js.js

4. Perform the test run using the following command

mongo --port 27117 < mongo_prune_js.js

5. If the mongo db is not running you might have to run the following command first

sudo mongod --dbpath /usr/lib/unifi/data/db

6. Once the test run is success you will need to edit mongo_prune_js.js to disable “dryrun”, change the line var dryrun=false;

nano mongo_prune_js.js

7. Prune the database by executing the following command, this will take a while to run depends on the size of events that you have. I had about 2 millions events.

mongo --port 27117 < mongo_prune_js.js

8. If all goes well you should see a couple of OK message like the following

{ "ok" : 1}

9. Change the db and log files permission using the following (NOTE : this is an important step)

chown -R unifi:unifi /usr/lib/unifi/data/db/
chown -R unifi:unifi /usr/lib/unifi/logs/server.log

10. Finally start the unifi service using the following

service unifi start

11. if all goes well you should be able to login to the unifi web interface now.

Posted on Leave a comment

LED Matrix Fibonacci Clock

I was inspired by all the Fibonacci clock out there, so I decided to design one my own. I am using the same LED Matrix circuit as described in earlier blog post.

So the idea is to show the Hours and Minute with the maximum of 12, it is behaving like the hour hand and minute hand displaying the time. So the left “Fibonacci” pattern is used to display the hour and the right Fibonacci pattern is used to display the minute.

I thought of displaying the seconds later, so that the clock seems alive, and the seconds is displayed using binary like the Binary clock in the previous post.

With the concept done, we are now ready to modify the Arduino code. But before that let’s have a look at how the pattern will be displayed in the following picture.

So the biggest challenge is to get the pattern combination right. To make sure the digit is showing correctly for each seconds, we need to make sure the data displayed correctly.

If you look at the output bytes, that is how it need to display to get the exact pattern as what is shown. For the seconds is showing in Binary we need to superimpose that on the pattern here. This is shown in the following code:

void display_seconds()
{
int sec_one = _second % 10;
int sec_ten = _second / 10;
output[0] = (sec_ten & 0x01) << 7 | (sec_one & 0x01) << 6 | (output[0] & 0x1F); // saved the previous minutes
output[1] = (sec_ten & 0x02) << 6 | (sec_one & 0x02) << 5 | (output[1] & 0x07);
output[2] = (sec_ten & 0x04) << 5 | (sec_one & 0x04) << 4 | (output[2] & 0x03);
output[3] = (sec_ten & 0x08) << 4 | (sec_one & 0x08) << 3 | (output[3] & 0x09);
}

As you can see to show the Seconds we need to break up the seconds into “one” and “ten” digit this is done in the first 2 line by dividing and modding the seconds with 10. Then the LSB will be shown in Output[0], and so on. Because the LED matrix LSB is at the bottom, we need to shift the digit 7 times for the “ten” to be displayed at the top, and the seconds will need to be shift 6 times to get it to the second row. Then we need to super impose the minute digit which is mask with Hexadecimal of 0x1F(the highest number for Output[0]). Thus the following code:

output[0] = (sec_ten & 0x01) << 7 | (sec_one & 0x01) << 6 | (output[0] & 0x1F);

The second bit is masked using 0x02 and because it is the second digit we only need to shift it 6 times for the “ten” and 5 times for the “one” and then masking the minute by 0x07 (the highest number for Output[1]). Hence the following code:

output[1] = (sec_ten & 0x02) << 6 | (sec_one & 0x02) << 5 | (output[1] & 0x07);

And so on until the last second digit, and hopefully you get the idea of the pattern.

The next challenge is to display the minute. To do that we need to understand the fibonacci number pattern first. We only use the first couple of numbers

1,1,2,3,5

Given the fibonacci numbers, number 1 can be represented either by the first 1 or the second 1 in the sequence, so we do a random number generator to choose which LED to light up. For number 2 can be represented by 1+1 or just 2, we also use the random number generator to choose which pattern to light up. Number 3 can be displayed as 2+1 (first), 2+1 (second) or just 3, this is also done using random number generator to choose which combination to light up. Continue this pattern until number 12 which need to light up 5+3+2+1+1. In simple terms, to read the minute we only need to count how many lights light up on the “right hand” corner. This is done in the following code:

void display_minute()
 {
   switch(_minute/5)
   {
     case 1:
       switch(random(2))
       {
         case 0:
           output[3] = 1; break;
         case 1:
           output[4] = 1; break;
  } break;
case 2:
  switch(random(2))
  {
    case 0:
      output[2] = 3; break;
    case 1:
      output[3] = 1;
      output[4] = 1; break;

  } break;
case 3:
  switch(random(3))
  {
    case 0:
      output[1] = 7; break;
    case 1:
      output[2] = 3;
      output[3] = 1; break;
    case 2:
      output[2] = 3;
      output[4] = 1; break;
  } break;
case 4:
  switch(random(3))
  {
    case 0:
      output[1] = 7;
      output[3] = 1; break;
    case 1:
      output[1] = 7;
      output[4] = 1; break;
    case 2:
      output[2] = 3;
      output[3] = 1;
      output[4] = 1; break;
  } break;
case 5:
  switch(random(3))
  {
    case 0:
      output[0] = 0x1F; break;
    case 1:
      output[1] = 7;
      output[2] = 3; break;
    case 2:
      output[2] = 3;
      output[3] = 1;
      output[4] = 1; break; 
  } break;
case 6:
  switch(random(4))
  {
    case 0:
      output[0] = 0x1F;
      output[3] = 1; break;
    case 1:
      output[0] = 0x1F;
      output[4] = 1; break;
    case 2:
      output[1] = 7;
      output[2] = 3;
      output[3] = 1; break;
    case 3:
      output[1] = 7;
      output[2] = 3;
      output[4] = 1; break;
  } break;
case 7:
  switch(random(3))
  {
    case 0:
      output[0] = 0x1F;
      output[2] = 3; break;
    case 1:
      output[0] = 0x1F;
      output[3] = 1;
      output[4] = 1; break;
    case 2:
      output[1] = 7;
      output[2] = 3;
      output[3] = 1;
      output[4] = 1; break;
  } break;
case 8:
  switch(random(3))
  {
    case 0:
      output[0] = 0x1F;
      output[1] = 7; break;
    case 1:
      output[0] = 0x1F;
      output[2] = 3;
      output[3] = 1; break;
    case 2:
      output[0] = 0x1F;
      output[2] = 3;
      output[4] = 1; break;
  } break;
case 9:
  switch(random(2))
  {
    case 0:
      output[0] = 0x1F;
      output[1] = 7;
      output[3] = 1; break;
    case 1:
      output[0] = 0x1F;
      output[1] = 7;
      output[4] = 1; break;
  } break;
case 10:
  switch(random(2))
  {
    case 0:
      output[0] = 0x1F;
      output[1] = 7;
      output[2] = 3; break;
    case 1:
      output[0] = 0x1F;
      output[1] = 7;
      output[3] = 1;
      output[4] = 1; break;
  } break;
case 11:
  switch(random(2))
  {
    case 0:
      output[0] = 0x1F;
      output[1] = 7;
      output[2] = 3; 
      output[3] = 1; break;
    case 1:
      output[0] = 0x1F;
      output[1] = 7;
      output[2] = 3;
      output[4] = 1; break;        
  } break;
case 12:
      output[0] = 0x1F;
      output[1] = 7;
      output[2] = 3; 
      output[3] = 1; 
      output[4] = 1; break;
}
}

We done the same with the top left corner of Fibonacci sequence to display the hour. However the one tricky bit is Output[3] and Output[4] is shared between hour and minute, so we need to mask the minute so that we didn’t lost it. This is done using the following code:

output[3] = 8 | (output[3] & 0x01);
output[4] = 8 | (output[4] & 0x01);

Then the output is combined and displayed. The full source code can be downloaded in the download section of shop. If you like this, please leave a comment or share it.

So the final result you can see in the following video:

Posted on Leave a comment

Connecting Touch sensor to Bluetooth Amplifier

TTP223 Touch sensor

First of all, I would like to wish everyone a Happy New year of 2019, this will be my first post of 2019. I hope you had a great start of the year.

I had discovered a capacitive touch sensor TTP223 which simulate a switch function by “touch”, it is using the capacitive of your hand or any other organic matter to allow the switch function. It can be configured to as “Toggle” or “On/Off”.

I recently post a review about various Bluetooth Amplifier that I had been testing. And the CSR8635 Dual 5W Bluetooth Amplifier had a particular interesting feature where you can “Skip” tracks, “Vol+” Vol-“, “Play/Pause” which also double up as “Pick up” call function. The problem with this is the Switch needs to connect each function to the “common” connection. So I am trying to experiment whether this will work using the touch sensor above.

Touch Sensor and Bluetooth Amplifier

The picture on the left shows how the functionality of the touch sensor. When the touch area is being touch, it will connect the I/O pin to the Vcc. While the Bluetooth Amplifier switch needs to connect the “Next” pin to the “common” pin. After some research the common pin is connected to Vcc. So I wonder whether I can connect the I/O pin straight away to the “Next” pin. So I had experimented using the circuit below, and it seems to work ok.

Connecting the Touch Sensor to Bluetooth Amplifier control pins

So I had connected a 10K ohm resistor to limit the current that flow from Vcc of the touch sensor to the Bluetooth amplifier. It seems to be working ok at this stage. I had connected 2 pin, the “Next” pin and “Play/pause” pin. Both seems to work ok.

You can see the final connection in the following picture.

Touch sensors connected to Bluetooth Amplifier controls

If you like this, please let me know or subscribe to the blog to receive frequent tips on simple circuits.