Posts Tagged ‘philrobokit’

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

Advertisements

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

};