Posts Tagged ‘Philrobotics’

A line follower is just like a hello world in robotics. Many have been made and nowadays are based on arduino boards, this time I want to go old school and build this simple line follower from parts on my bin. The DS89C430 is a fast 8051 core variant from Maxim, before the era of arduino these are the microcontrollers that only requires UART connection and do not require a external programmer to load the bootloader because it is loaded with bootloader already from the factory and only a terminal program is required to load the hex file generated from the assembler or compiler.

This line follower consist of 3 TCRT5000 reflective IR sensors that goest to a LM339 quad comparator that gives the microcontroller a high or low signal when a black line is detected or not. A L9110S motor driver module was used to drive the two DC motors in differential drive mode. The whole project is powered by a single 3.7V 18650 battery from an old laptop battery pack. The output is fed to a boost converter based on the classic MC34063 to boost the battery voltage to 5V. The complete schematic is show below.

follower

Schematic Diagram

The whole project is built on a strip board with mixed thru hole and surface mount components depending on what I have on my bin.

P_20161231_111255.jpg

P_20161231_111512.jpg

And now the code! Basically a logic based on its position on the track. One motor is stopped to make a turn. The code is compiled with SDCC.

code.PNG

Voila! a nice line follower that can navigate even a complicated track! See the video demo below

Advertisements

This project was lost, luckily while digging I found a backup file. I am now making this project available for public use. Released as is with no warranties, I am not liable for any harm done to your system. This should be used ONLY FOR EDUCATIONAL PURPOSES. The client file requires .NET Framework 4.0. The arduino sketch was compiled and tested with Arduino IDE 1.0.5 and Gizduino 328 (Arduino clone in the Philippines by e-Gizmo Mechatronics Central). The program for the 8051 was compiled with SDCC.

Screen

Connection Diagram:

Schematic

Instructions:
1. Select the Correct COM Port
2. Connect
3. Load up the Hex file
4. Upload Hex file to your MCU
5. Grab a beer and enjoy!

Click the Link below for the sketch and the client
DOWNLOAD FILES HERE

A month ago while browsing at ebay I came across this Bluetooth Audio Receiver and its on sale so I gave it a shot. At first it is a little difficult because all literature available are all in chinese, but luckily I found a readable manual. The exact model of this module is BLK-MD-SPK-D. I found out that there are several models and they look the same.Bluetooth Module

Finally when it arrived, I quickly made a breakout board to test its functionality, and it turned out it sounds great and its stereo. Eagle library and manual can be downloaded from the link below for those who need it.

Breakout Board

Eagle Files and Manual Download Link Click Here

This is my first post for the year, been busy for a while. The Pbot is an entry level mobile robot learning platform locally available in e-gizmo here in the Philippines. It contains three channel IR collision sensor, 3 Channel line sensor and a dual motor driver. Any arduino compatible platform can be used as the controller. It is a fun mobot platform to play with, can be configured as a line follower, a mazer or a sumobot or even a soccer bot.
Pbot

A quick weekend project to play with this mobot platform is to control it with VB.net thru Bluetooth Serial Port. When playing with these toys, it is important to know whether your battery still have the juice so you can enjoy playing, but the old board (that I have) don’t have a connection for battery feedback. My quick solution is to put a voltage divider (two 100K resistors) between the battery terminals and feed it to the Analog Input 0 of the controller.

Remote

The Arduino program transmits data every second to the computer then waits for a character from the Computer, When a correct character is received, then it tells the motors what to do.

Voila! Vb.net Controlled Pbot with Battery Status Feedback

The code listing for the Arduino

/*
'Pbot Remote Control with VB.net 2010
'Copyright (C) 2014 Richard Myrick T. Arellaga
'
'This program is free software: you can redistribute it and/or modify
'it under the terms of the GNU General Public License as published by
'the Free Software Foundation, either version 3 of the License, or
'(at your option) any later version.
'
'This program is distributed in the hope that it will be useful,
'but WITHOUT ANY WARRANTY; without even the implied warranty of
'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
'GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see .
*/

int batt = 0;
float voltage = 0;

long prevMillis = 0;
long interval = 1000;
int rx = 0;

const int M1DIR = 8;
const int M1RUN = 9;
const int M2RUN = 10;
const int M2DIR = 11;

void setup()
{
pinMode(M1DIR,OUTPUT);
pinMode(M1RUN,OUTPUT);
pinMode(M2RUN,OUTPUT);
pinMode(M2DIR,OUTPUT);

Serial.begin(9600);

}

void loop()
{
//Run RTC and send battery update every second
unsigned long currentMillis = millis();
if(currentMillis - prevMillis > interval)
{

prevMillis = currentMillis;
batt = analogRead(0);
voltage = (batt/1023.0)* (2 * readVcc());
Serial.println(voltage);

}

//check serial port character receive
if(Serial.available()){
rx=Serial.read();

if(rx == 'W')
{
digitalWrite(M1DIR,HIGH);
analogWrite(M1RUN,250);
analogWrite(M2RUN,250);
digitalWrite(M2DIR,HIGH);
rx = 0;
}else if(rx == 'Q')
{
digitalWrite(M1DIR,LOW);
analogWrite(M1RUN,0);
analogWrite(M2RUN,0);
digitalWrite(M2DIR,LOW);
rx = 0;
}else if(rx == 'S')
{
digitalWrite(M1DIR,LOW);
analogWrite(M1RUN,250);
analogWrite(M2RUN,250);
digitalWrite(M2DIR,LOW);
rx = 0;
} else if(rx == 'D')
{
digitalWrite(M1DIR,HIGH);
analogWrite(M1RUN,250);
analogWrite(M2RUN,0);
digitalWrite(M2DIR,LOW);
rx = 0;
}
else if(rx == 'A')
{
digitalWrite(M1DIR,LOW);
analogWrite(M1RUN,0);
analogWrite(M2RUN,250);
digitalWrite(M2DIR,HIGH);
rx = 0;
}
}
}

//read actual VCC of arduino for a more accurate adc reading
long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate AVcc in mV

return result/1000;
}

VB.net Code Listing


'Pbot Remote Control with VB.net 2010
'Copyright (C) 2014 Richard Myrick T. Arellaga
'
'This program is free software: you can redistribute it and/or modify
'it under the terms of the GNU General Public License as published by
'the Free Software Foundation, either version 3 of the License, or
'(at your option) any later version.
'
'This program is distributed in the hope that it will be useful,
'but WITHOUT ANY WARRANTY; without even the implied warranty of
'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
'GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see .

Imports System.IO.Ports
Imports System.Text

Public Class Form1

Private pendingMsg As New StringBuilder()

Private Sub GetCOMPortList()
Dim i As Integer
Dim foundDifference = False

If cboCOMPorts.Items.Count = SerialPort.GetPortNames().Length Then
For Each s As String In SerialPort.GetPortNames()
If cboCOMPorts.Items(System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)).Equals(s) = False Then
foundDifference = True
End If
Next
Else
foundDifference = True
End If

If foundDifference = False Then
Return
End If

cboCOMPorts.Items.Clear()

For Each s As String In SerialPort.GetPortNames()
cboCOMPorts.Items.Add(s)
Next
cboCOMPorts.SelectedIndex = 0

End Sub

Private Sub serialPort1_DataReceived(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived

Dim completeMsg As String
completeMsg = String.Empty

pendingMsg.Append(SerialPort1.ReadExisting())

If pendingMsg.Length >= 6 Then
completeMsg = pendingMsg.ToString(0, 6)
pendingMsg.Remove(0, 6)
Me.Invoke(New Action(
Sub()
txtRxData.Text = completeMsg
End Sub))
End If

End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
btnDisconnect.Enabled = False
GetCOMPortList()
End Sub

Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click

Try
SerialPort1.PortName = cboCOMPorts.Items(cboCOMPorts.SelectedIndex).ToString()
SerialPort1.BaudRate = 9600
SerialPort1.ReadTimeout = 1000
SerialPort1.Open()
btnDisconnect.Enabled = True
btnConnect.Enabled = False
Catch ex As Exception
btnDisconnect.PerformClick()
End Try
End Sub

Private Sub btnDisconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisconnect.Click
Try
SerialPort1.DiscardInBuffer()
SerialPort1.DiscardOutBuffer()
SerialPort1.Close()
btnConnect.Enabled = True
btnDisconnect.Enabled = False
Catch ex As Exception

End Try
End Sub

Private Sub btnFW_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFW.Click
If (SerialPort1.IsOpen()) Then
SerialPort1.Write("W")

End If
End Sub

Private Sub btnBack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBack.Click
If (SerialPort1.IsOpen()) Then
SerialPort1.Write("S")

End If
End Sub

Private Sub btnLeft_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLeft.Click
If (SerialPort1.IsOpen()) Then
SerialPort1.Write("A")

End If
End Sub

Private Sub btnRight_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRight.Click
If (SerialPort1.IsOpen()) Then
SerialPort1.Write("D")

End If
End Sub

Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click
If (SerialPort1.IsOpen()) Then
SerialPort1.Write("Q")

End If
End Sub
End Class

LED signs are everywhere and they can be bought dirt chip nowadays, but the feeling is good if you can build your own. This project is based on Atmega328P with Arduino UNO bootloader and some shift registers and a driver. The schematic shown is the complete circuit of the project. You notice that there are even no current limiting resistors, the LED matrix is directly driven by the shift register. This circuit is just for testing and is not guaranteed for a long period of operation. The message buffer can accommodate up to 100 characters.

The demo video is a little garbled because I am only using a mobile phone , but the actual device the message is clear.

8x32Matrix

Schematic Diagram

A simple message uploader written in C# can be download from here. The uploader requires .NET Framework 4.0 Installed.

Message Uploader

Message Uploader

Arduino Sketch


#include "cmap.h"

int d;
unsigned char char_pointer;
char Display_Ram[38];
unsigned char mask;
char LED_DATA[100]= "8x32 LED Scrolling Message Display by tiktak 2013 ~";
char LED_BUFFER[100];
char count;
unsigned char shift_counter;
int rxctr = 0;

#define INTEN 6500

const char DAT = 8;
const char CLK = 10;
const char LAT = 9;

const char DAT1 = 11;
const char CLK1 = 13;
const char LAT1 = 12;
int i = 0;
void setup() {
 pinMode(CLK, OUTPUT);
 pinMode(DAT, OUTPUT);
 pinMode(CLK1, OUTPUT);
 pinMode(DAT1, OUTPUT);
 pinMode(LAT, OUTPUT);
 pinMode(LAT1, OUTPUT);

 Serial.begin(9600);

}

void loop(){
 if(Serial.available()){
 int rx = Serial.read();
 LED_BUFFER[rxctr] = rx;
 rxctr++;
 if(rx == '~'){
 for(int h=0; h<100; h++){
 LED_DATA[h] = 0;
 }
 rxctr = 0;
 for(int x = 0; x<100; x++){
 LED_DATA[x] = LED_BUFFER[x];
 }
 Clear_Display_Ram();
 }
 }

 Display();
 shift();
}

void scanRow(unsigned char row)
{
 int i;
 for(i = 0; i<8; i++)
 {
 if(row & 0x80){
 digitalWrite(DAT1,HIGH);
 }
 else{
 digitalWrite(DAT1,LOW);
 }

 digitalWrite(CLK1,HIGH);
 digitalWrite(CLK1,LOW);

 row <<= 1;
 }
 digitalWrite(LAT1,HIGH);
 digitalWrite(LAT1,LOW);

}

void shift(void)
{
 int x;
 for(x=0; x<38; x++){
 Display_Ram[x] = Display_Ram[x+1];
 }

shift_counter++;
 if(shift_counter == 6){
 shift_counter = 0;
 load();
 }

}

void Display(void)
{
 mask = 0x01;
 scan();
 scanRow(0x80);
 for(d=0;d<INTEN;d++){}
 scanRow(0x00);

mask = 0x02;
 scan();
 scanRow(0x40);
 for(d=0;d<INTEN;d++){}
 scanRow(0x00);

mask = 0x04;
 scan();
 scanRow(0x20);
 for(d=0;d<INTEN;d++){}
 scanRow(0x00);

mask = 0x08;
 scan();
 scanRow(0x10);
 for(d=0;d<INTEN;d++){}
 scanRow(0x00);

mask = 0x10;
 scan();
 scanRow(0x08);
 for(d=0;d<INTEN;d++){}
 scanRow(0x00);

mask = 0x20;
 scan();
 scanRow(0x04);
 for(d=0;d<INTEN;d++){}
 scanRow(0x00);

mask = 0x40;
 scan();
 scanRow(0x02);
 for(d=0;d<INTEN;d++){}
 scanRow(0x00);

mask = 0x80;
 scan();
 scanRow(0x01);
 for(d=0;d<INTEN;d++){}
 scanRow(0x00);
}

void load(void){
 char counter1;
 if(LED_DATA[char_pointer+1] == '~')
 char_pointer = 0;
 for(counter1 = 0; counter1 < 5; counter1++){
 Display_Ram[32 + counter1] = character_data[(LED_DATA[char_pointer] - 0x20)][counter1];
 }
 Display_Ram[37] = 00;
 char_pointer++;
}

void Clear_Display_Ram(void){
 unsigned char rcount;
 for(rcount = 0; rcount < 37; rcount++)
 Display_Ram[rcount] = 0x00;
}

void scan(void){
 for (count=0;count<32;count++){
 if ((Display_Ram[count] & mask) == mask)
 digitalWrite(DAT,HIGH);
 else
 digitalWrite(DAT,LOW);
 digitalWrite(CLK,HIGH);
 digitalWrite(CLK,LOW);
 }
 digitalWrite(LAT,HIGH);
 digitalWrite(LAT,LOW);
}

cmap.h


const unsigned char character_data[][6] =
{
 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, //20-
 { 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00 }, //21-!
 { 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00 }, //22-"
 { 0x28, 0xFE, 0x28, 0xFE, 0x28, 0x00 }, //23-#
 { 0x24, 0x54, 0x7E, 0x54, 0x48, 0x00 }, //24-$
 { 0xC4, 0xC4, 0x10, 0x26, 0x46, 0x00 }, //25-%
 { 0x6C, 0x92, 0xAA, 0x44, 0x1A, 0x00 }, //26-&
 { 0x00, 0x00, 0xA0, 0xC0, 0x00, 0x00 }, //27-'
 { 0x00, 0x00, 0x38, 0x44, 0x82, 0x00 }, //28-(
 { 0x00, 0x82, 0x44, 0x38, 0x00, 0x00 }, //29-)
 { 0x28, 0x10, 0x6C, 0x10, 0x28, 0x00 }, //2A-*
 { 0x10, 0x10, 0x6C, 0x10, 0x10, 0x00 }, //2B-+
 { 0x00, 0x00, 0x0A, 0x0C, 0x00, 0x00 }, //2C-,
 { 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 }, //2D--
 { 0x00, 0x00, 0x06, 0x06, 0x00, 0x00 }, //2E-.
 { 0x04, 0x08, 0x10, 0x20, 0x40, 0x00 }, //2F-/
 { 0x7C, 0x82, 0x82, 0x82, 0x7C, 0x00 }, //30
 { 0x00, 0x42, 0xFE, 0x02, 0x00, 0x00 }, //31
 { 0x42, 0x86, 0x8A, 0x92, 0x62, 0x00 }, //32
 { 0x84, 0x82, 0xA2, 0xD2, 0x8C, 0x00 }, //33
 { 0x18, 0x28, 0x48, 0xFE, 0x08, 0x00 }, //34
 { 0xE4, 0xA2, 0xA2, 0xA2, 0x9C, 0x00 }, //35
 { 0x3C, 0x52, 0x92, 0x92, 0x0C, 0x00 }, //36
 { 0x80, 0x8E, 0x90, 0xA0, 0xC0, 0x00 }, //37
 { 0x6C, 0x92, 0x92, 0x92, 0x6C, 0x00 }, //38
 { 0x60, 0x92, 0x92, 0x94, 0x78, 0x00 }, //39
 { 0x00, 0x00, 0x6C, 0x6C, 0x00, 0x00 }, //3A-:
 { 0x00, 0x00, 0x6A, 0x6C, 0x00, 0x00 }, //3B-//
 { 0x00, 0x10, 0x28, 0x44, 0x82, 0x00 }, //3C-<
 { 0x28, 0x28, 0x28, 0x28, 0x28, 0x00 }, //3D-=
 { 0x00, 0x82, 0x44, 0x28, 0x10, 0x00 }, //3E->
 { 0x40, 0x80, 0x8A, 0x90, 0x60, 0x00 }, //3F-?
 { 0x7C, 0x82, 0xBA, 0xAA, 0xBA, 0x70 }, //40-@
 { 0x7E, 0x88, 0x88, 0x88, 0x7E, 0x00 }, //41-A
 { 0xFE, 0x92, 0x92, 0x92, 0x6C, 0x00 }, //42-B
 { 0x7C, 0x82, 0x82, 0x82, 0x44, 0x00 }, //43-C
 { 0xFE, 0x82, 0x82, 0x44, 0x38, 0x00 }, //44-D
 { 0xFE, 0x92, 0x92, 0x92, 0x82, 0x00 }, //45-E
 { 0xFE, 0x90, 0x90, 0x90, 0x80, 0x00 }, //46-F
 { 0x7C, 0x82, 0x92, 0x92, 0x5E, 0x00 }, //47-G
 { 0xFE, 0x10, 0x10, 0x10, 0xFE, 0x00 }, //48-H
 { 0x00, 0x82, 0xFE, 0x82, 0x00, 0x00 }, //49-I
 { 0x04, 0x02, 0x82, 0xFC, 0x80, 0x00 }, //4A-J
 { 0xFE, 0x10, 0x28, 0x44, 0x82, 0x00 }, //4B-K
 { 0xFE, 0x02, 0x02, 0x02, 0x02, 0x00 }, //4C-L
 { 0xFE, 0x40, 0x30, 0x40, 0xFE, 0x00 }, //4D-M
 { 0xFE, 0x20, 0x10, 0x08, 0xFE, 0x00 }, //4E-N
 { 0x7C, 0x82, 0x82, 0x82, 0x7C, 0x00 }, //4F-O
 { 0xFE, 0x90, 0x90, 0x90, 0x60, 0x00 }, //50-P
 { 0x7C, 0x82, 0x8A, 0x84, 0x7A, 0x00 }, //51-Q
 { 0xFE, 0x90, 0x98, 0x94, 0x62, 0x00 }, //52-R
 { 0x62, 0x92, 0x92, 0x92, 0x8C, 0x00 }, //53-S
 { 0x80, 0x80, 0xFE, 0x80, 0x80, 0x00 }, //54-T
 { 0xFC, 0x02, 0x02, 0x02, 0xFC, 0x00 }, //55-U
 { 0xF8, 0x04, 0x02, 0x04, 0xF8, 0x00 }, //56-V
 { 0xFC, 0x02, 0x1C, 0x02, 0xFC, 0x00 }, //57-W
 { 0xC6, 0x28, 0x10, 0x28, 0xC6, 0x00 }, //58-X
 { 0xE0, 0x10, 0x0E, 0x10, 0xE0, 0x00 }, //59-Y
 { 0x86, 0x8A, 0x92, 0xA2, 0xC2, 0x00 }, //5A-Z
 { 0x00, 0x00, 0xFE, 0x82, 0x82, 0x00 }, //5B-[
 { 0x40, 0x20, 0x10, 0x08, 0x04, 0x00 }, //5C-\

{ 0x00, 0x82, 0x82, 0xFE, 0x00, 0x00 }, //5D-]
 { 0x20, 0x40, 0xFE, 0x40, 0x20, 0x00 }, //5E-^
 { 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 }, //5F-_
 { 0x80, 0x40, 0x20, 0x00, 0x00, 0x00 }, //60-`
 { 0x04, 0x2A, 0x2A, 0x2A, 0x1E, 0x00 }, //61-a
 { 0xFE, 0x12, 0x22, 0x22, 0x1C, 0x00 }, //62-b
 { 0x1C, 0x22, 0x22, 0x22, 0x04, 0x00 }, //63-c
 { 0x1C, 0x22, 0x22, 0x12, 0xFE, 0x00 }, //64-d
 { 0x1C, 0x2A, 0x2A, 0x2A, 0x18, 0x00 }, //65-e
 { 0x08, 0x3F, 0x48, 0x40, 0x20, 0x00 }, //66-f
 { 0x18, 0x25, 0x25, 0x25, 0x3E, 0x00 }, //67-g
 { 0xFE, 0x10, 0x20, 0x20, 0x1E, 0x00 }, //68-h
 { 0x00, 0x22, 0xBE, 0x02, 0x00, 0x00 }, //69-i
 { 0x02, 0x01, 0x21, 0xBE, 0x00, 0x00 }, //6A-j
 { 0x00, 0xFE, 0x08, 0x14, 0x22, 0x00 }, //6B-k
 { 0x00, 0x82, 0xFE, 0x02, 0x00, 0x00 }, //6C-l
 { 0x3E, 0x20, 0x18, 0x20, 0x1E, 0x00 }, //6D-m
 { 0x3E, 0x10, 0x20, 0x20, 0x1E, 0x00 }, //6E-n
 { 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00 }, //6F-o
 { 0x3F, 0x24, 0x24, 0x24, 0x18, 0x00 }, //70-p
 { 0x18, 0x24, 0x24, 0x14, 0x3F, 0x00 }, //71-q
 { 0x3E, 0x10, 0x20, 0x20, 0x10, 0x00 }, //72-r
 { 0x12, 0x2A, 0x2A, 0x2A, 0x04, 0x00 }, //73-s
 { 0x20, 0xFC, 0x22, 0x02, 0x04, 0x00 }, //74-t
 { 0x3C, 0x02, 0x02, 0x04, 0x3E, 0x00 }, //75-u
 { 0x38, 0x04, 0x02, 0x04, 0x38, 0x00 }, //76-v
 { 0x3C, 0x02, 0x0C, 0x02, 0x3C, 0x00 }, //77-w
 { 0x22, 0x14, 0x08, 0x14, 0x22, 0x00 }, //78-x
 { 0x38, 0x05, 0x05, 0x05, 0x3E, 0x00 }, //79-y
 { 0x22, 0x26, 0x2A, 0x32, 0x22, 0x00 }, //7A-z
 { 0x00, 0x10, 0x6C, 0x82, 0x00, 0x00 }, //7B-{
 { 0x00 }, //7C-|-BLANK BAR
 { 0x00, 0x82, 0x6C, 0x10, 0x00, 0x00 }, //7D-}
 { 0x18, 0x24, 0x7E, 0x24, 0x08, 0x00 },
 { 0 } //7F-DO NOT USE

};

The serial port on our computers are with us for quite sometime now. It is more favored than the parallel port for interfacing with the outside world because it require lesser wires and can go farther distance and can even be used with newer technologies such as Bluetooth using its serial port capability. In this tutorial is a quick start guide in communicating with the serial port using VB.net without any previous knowledge.

Before we start, VB.net 2010 must be installed. The installer can be freely downloaded from Microsoft.

Start Visual Basic 2010 Express and you will be prompted with the Start Page Window

Select on New Project and select Windows Form Application and give the Project a name, in this case I named it Serial Port Interface.

A blank form will be displayed named Form1. This is the main form which will contain all other controls.

Click on the toolbox to show the  controls, you may want to click on the pin to disable the autohide feature

Click on the form and change its name to frmMain (for easier identification specially when adding more forms). Also, change its name, in this case VB.net Terminal – Philrobotics. This name will be the one that will be displayed on the title bar.  Since this program is only a small program, we can disable the Maximize button by setting MaximizeBox value on the form’s property to false.

Let’s start to add some controls to our form. From the common Controls, add (2) two labels, (2) two combo box and (2) two buttons. Change the text of the first label to “Com Port:” and the second one to “Baud Rate:”. For the combo box change its name to cmbPort and cmbBaud for the purposes of easier identification when we will add the codes to our controls. Also, change the text of the two buttons, the first to “Connect” and the second to “Disconnect” and change their name to btnConnect and btnDisconnect. As you can see, I use cmb and btn prefix to refer to combo box and button same reason as above, for easier identification.

Next, from the Containers add two Group box and change its text to “Transmit Data” and “Received Data”. Inside the Transmit Data group box, add a textbox and a button. Change the name of the textbox to txtTransmit and the button to btnSend, also change its text to Send. On the Received Data group box, add a Rich Text Box and change its name to rtbReceived. Lastly and the most important, add the SerialPort from the components.

Now, we come to the next part, adding the instructions to our program. To start coding double click the form or press F7 to view the code. To add a code to individual controls just go back to the designer view or press Shift+F7 and double click a control to add code into it.

For instance if we double click on the Send button on the designer view the Code Editor will take us to

Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click

On this Part is where we enter our codes.

End Sub

To complete our program put the following codes to the code editor:

‘Serial Port Interfacing with VB.net 2010 Express Edition
‘Copyright (C) 2010  Richard Myrick T. Arellaga

‘This program is free software: you can redistribute it and/or modify
‘it under the terms of the GNU General Public License as published by
‘the Free Software Foundation, either version 3 of the License, or
‘(at your option) any later version.

‘This program is distributed in the hope that it will be useful,
‘but WITHOUT ANY WARRANTY; without even the implied warranty of
‘MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
‘GNU General Public License for more details.

‘ You should have received a copy of the GNU General Public License
‘ along with this program.  If not, see <http://www.gnu.org/licenses/&gt;.

Imports System
Imports System.ComponentModel
Imports System.Threading
Imports System.IO.Ports
Public Class frmMain
Dim myPort As Array  ‘COM Ports detected on the system will be stored here
Delegate Sub SetTextCallback(ByVal [text] As String) ‘Added to prevent threading errors during receiveing of data

Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
‘When our form loads, auto detect all serial ports in the system and populate the cmbPort Combo box.
myPort = IO.Ports.SerialPort.GetPortNames() ‘Get all com ports available
cmbBaud.Items.Add(9600)     ‘Populate the cmbBaud Combo box to common baud rates used
cmbBaud.Items.Add(19200)
cmbBaud.Items.Add(38400)
cmbBaud.Items.Add(57600)
cmbBaud.Items.Add(115200)

For i = 0 To UBound(myPort)
cmbPort.Items.Add(myPort(i))
Next
cmbPort.Text = cmbPort.Items.Item(0)    ‘Set cmbPort text to the first COM port detected
cmbBaud.Text = cmbBaud.Items.Item(0)    ‘Set cmbBaud text to the first Baud rate on the list

btnDisconnect.Enabled = False           ‘Initially Disconnect Button is Disabled

End Sub

Private Sub btnConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnConnect.Click
SerialPort1.PortName = cmbPort.Text         ‘Set SerialPort1 to the selected COM port at startup
SerialPort1.BaudRate = cmbBaud.Text         ‘Set Baud rate to the selected value on

‘Other Serial Port Property
SerialPort1.Parity = IO.Ports.Parity.None
SerialPort1.StopBits = IO.Ports.StopBits.One
SerialPort1.DataBits = 8            ‘Open our serial port
SerialPort1.Open()

btnConnect.Enabled = False          ‘Disable Connect button
btnDisconnect.Enabled = True        ‘and Enable Disconnect button

End Sub

Private Sub btnDisconnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDisconnect.Click
SerialPort1.Close()             ‘Close our Serial Port

btnConnect.Enabled = True
btnDisconnect.Enabled = False
End Sub

Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
SerialPort1.Write(txtTransmit.Text & vbCr) ‘The text contained in the txtText will be sent to the serial port as ascii
‘plus the carriage return (Enter Key) the carriage return can be ommitted if the other end does not need it
End Sub

Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
ReceivedText(SerialPort1.ReadExisting())    ‘Automatically called every time a data is received at the serialPort
End Sub
Private Sub ReceivedText(ByVal [text] As String)
‘compares the ID of the creating Thread to the ID of the calling Thread
If Me.rtbReceived.InvokeRequired Then
Dim x As New SetTextCallback(AddressOf ReceivedText)
Me.Invoke(x, New Object() {(text)})
Else
Me.rtbReceived.Text &= [text]
End If
End Sub

Private Sub cmbPort_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbPort.SelectedIndexChanged
If SerialPort1.IsOpen = False Then
SerialPort1.PortName = cmbPort.Text         ‘pop a message box to user if he is changing ports
Else                                                                               ‘without disconnecting first.
MsgBox(”Valid only if port is Closed”, vbCritical)
End If
End Sub

Private Sub cmbBaud_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmbBaud.SelectedIndexChanged
If SerialPort1.IsOpen = False Then
SerialPort1.BaudRate = cmbBaud.Text         ‘pop a message box to user if he is changing baud rate
Else                                                                                ‘without disconnecting first.
MsgBox(”Valid only if port is Closed”, vbCritical)
End If
End Sub
End Class

After putting all the codes we are now ready to compile our project. To do this go to, Debug -> Build SerialPortInterface.  If there are no errors, It will indicate Build Succeeded at the status bar.

The executable file of the compiled project is usually located at the bin\Release of the project folder.

To test if our program is working, short the TX and RX pin of your serial port and  press F5 or click on the green triangle. Each data that we send must also be received by our program. In my setup I’m using a USB-to-Serial Converter and is allocated at COM18.

[Updated] Downlink link for project source