Major help with VB -> Arduino

Asking people to write a program for you won't get much of a response here (or on most development support forums).

You said that you got this working in Processing, why would you want to redo it in .NET. Nothing wrong with wanting to redo it, just wondering why.

What's not working in .NET, or what are you stuck on? While the code would be different, the concepts would be the same.

From the post on the other forum, I couldn't even begin to guess at what to write, since I don't know what your Arduino code looks like, or how you were doing it in Processing.

In short, you're going to have to post a lot more info to get some help with this.

Hi Du-z,

You might want to have a look at the sample applications on this site:

Especially the ArduinoFirmataVBExtended.zip on the Downloads page. This is a Visual Basic.NET application that communicates to the Arduino which is running Standard Firmata. Firmata is a ready-made protocol for communicating with the Arduino.

Regards,

Andrew

yeah ive been eyeing this, so the idea behind this is so i can modify it to my use?

what if i wanted to use my own protocol?

0 = off
1 = white
2 = green
ect....

Sorry about my ignorance Robert.

Hi Du-z,

Yes you can modify the Firmata protocol if you want to and you can certainly modify the FirmataVB code for your own needs (you're encouraged to do so)

To turn on/off some LEDs you can use the Standard Firmata sketch as it is. Load this onto your board. Connect LEDs to as many digital pins as you like (pins 2 - 13).

You would then send messages to the board from your software using the Firmata protocol. This is where the FirmataVB code comes in. You would adapt it to do what you want. You can either set up buttons in your VB project to turn on/off LEDs or have the user type in values that the software then sends to the board.

Not sure from you're reply whether you intend trying to control RGB LEDs but if you did you could use the PWM pins to 'mix' the colours.

Anyway, the best way to find out how it all works is to try it out

I'd suggest you...

  • Upload the Standard Firmata sketch to your board
  • Download and extract the ArduinoFirmataVBExtended zip file from the download page at FirmataVB - Downloads page
  • Navigate to the following folder in the download ArduinoFirmataVBExtended\ArduinoFirmataVBExtended\ArduinoFirmataVBExtended\bin\Release
  • Double click the ArduinoFirmataVBExtended.exe file and try this out with a few LEDs connected to your board.

Regards,

Andrew Craigie

sweet I will give this a go!

yes I am using RGB LEDs on the PWM pins.

Unfortunately Firmata is not working it is not working, and it is not as streamline as i would like later on as i might be making a few of these for friends.

However i have made a sketch for the Arduino. How will i be able to make this work with VB?

From what i can see this code will work.

    By Du-z
 
 Notes:
 
 EEPROM Addresses:
 1 = Red LED Colour
 2 = Green LED Colour
 3 = Blue LED Colour
 
 
 
 */

#include <EEPROM.h>
#include <LED.h>

LED ledboot_ok = LED(13);//declare digital pin 13 as the boot ok LED.
LED ledr = LED(11);//declare digital pin 11 as a Red LED's.
LED ledb = LED(10);//declare digital pin 10 as a Blue LED's.
LED ledg = LED(9); //declare digital pin 9 as a Green LED's.
int com;




void setup()
{
  Serial.begin(9600); // opens the com port and sets it at 9600 baud
  ledr.setValue(EEPROM.read(1)), ledg.setValue(EEPROM.read(2)), ledb.setValue(EEPROM.read(3)); // sets LEDs and fans to previous settings before reset.
  ledboot_ok.setValue(255); // Turns boot_ok LED on
}

void loop()
{
  if (Serial.available()) 
  {
    com = Serial.read();

    // This is for the red LEDs
    if (com >= 1000 && com <= 1225) {
      ledr.setValue( com - 1000); 
      EEPROM.write(1, com - 1000);
    }
    // This is for the green LEDs
    if (com >= 2000 && com <= 2255) {
      ledg.setValue(com - 2000); 
      EEPROM.write(2, com - 2000);
    }
    // This is for the blue LEDs
    if (com >= 3000 && com <= 3255) {
      ledg.setValue(com - 3000); 
      EEPROM.write(3, com - 3000);
    }
  }
}

How can i make this a reality?

Edit: Sorry for the double post. :-[

Hi again,

Not sure what you mean by 'Firmata is not working'!?! I'm assuming you mean it is not working for you and as your post suggests it is not working for you in the way you would like it to. With Firmata running on your Arduino and using the FirmataVB component you could easily implement a small program in VB.NET or C#.NET to send PWM to any/all of the 6 PWM pins on the Arduino. The issue is then one of knowing how to write the .NET application. Forgive me if i'm wrong on this but it seems that is where you're looking for support.

To 'simply' control your LEDs you don't, of course, need to use Firmata. You do however need to create your own protocol and write not only the Arduino sketch to receive it but to write the VB.NET application as well. You've made a start with the Arduino sketch.

A few comments on your Arduino sketch first:

You appear to be trying to set the value of Pin 13 to 255. Pin 13 is not a PWM pin so to turn it on you'd use digitalWrite(ledboot_ok, HIGH) and to turn it off you'd use digitalWrite(ledboot_ok, LOW).

It looks like you want to send values of 1000 - 1225, 2000 - 2225, 3000 - 3255 to the Arduino from your computer. Any of these values would require you to send 2 bytes. Nothing wrong with that but using com = Serial.read() will only read the first byte you send and as your code stands all of the if statements would be false all of the time.

If you're going to write your own sketch (rather than using Firmata) you will need to write it to accept at least 2 bytes at a time.

Something like the following might work:

 if (Serial.available())
  {
    // read the first byte (1, 2 or 3)
    LEDtoSet = Serial.read();
    delay(100);  // this line may not be necessary
    // read the next byte (0 - 255)
    PWMvalue = Serial.read();

    // code here to then set the LED PWM value
    analogWrite(LEDtoSET, PWMvalue);

  }

Doing it that way you'd have to send 3 seperate 2 byte messages from your computer to set the LEDs. An alternative approach would be to have the Arduino sketch accept a 4 byte message. The first byte would be the RGB 'cluster' number then the next 3 bytes would be the R, G & B values. Slightly more complex Arduino sketch but would cut down on data sent and be easier to implement in VB.

In Visual Basic (or C#) a simple program that does the following would work:

  • Configure a serial port with the name of the port your using and the baud rate your using
  • Open the serial port
  • Send the bytes you want to send

I'd include a some VB code for you but work beckons.

Cheers,

Andrew Craigie

ill get that PWM on LED 13 fixed and yes the VB stuff is were i need the help really, the tutorials for Arduino are great.

i like that cluster idea i was actually tried that with processing when i was trying to figure out what was best as far as the protocol goes. i needed to have a 50ms delay in there to wait for the next value.

so basically the first if thing that is sent over the serial is the 'colour' and the next will be the actally LED PWM value

thanks mate :slight_smile:

Heres the new sketch, but its not working both the 'on' and 'off' buttons turns all of the LEDs on. (i have comented out the EEPROM stuff to make it simpler)

Arduino Sketch:

/*
   /*
    By Du-z
 
 Notes:
 
 EEPROM Addresses:
 1 = Red LED Colour
 2 = Green LED Colour
 3 = Blue LED Colour
 
 To Do:
 
 Add Fan Controler.
 Serial/Program Active LED ???
 
 */

#include <EEPROM.h> //  http://www.arduino.cc/en/Reference/EEPROM
#include <LED.h>    //  http://www.arduino.cc/playground/Code/LED

LED ledboot_ok = LED(13);//declare digital pin 13 as the boot ok LED.
LED ledr = LED(11);//declare digital pin 11 as a Red LED's.
LED ledb = LED(10);//declare digital pin 10 as a Blue LED's.
LED ledg = LED(9); //declare digital pin 9 as a Green LED's.
int com;
int colour;

void setup()
{
  Serial.begin(9600); // opens the com port and sets it at 9600 baud
  //ledr.setValue(EEPROM.read(1)), ledg.setValue(EEPROM.read(2)), ledb.setValue(EEPROM.read(3)); // sets LEDs and fans to previous settings before it was reset/turned off.
  ledboot_ok.on(); // Turns boot_ok LED on
}

void loop()
{
  if (Serial.available()) 
  {
    com = Serial.read();

    // This is for the red LEDs
    if (com = 1) {
      colour = Serial.read();
      ledr.setValue(colour); 
      //EEPROM.write(1, colour);
    }
    // This is for the green LEDs
    if (com = 2) {
      colour = Serial.read();
      ledg.setValue(colour); 
      //EEPROM.write(2, colour);
    }
    // This is for the blue LEDs
    if (com = 3) {
      colour = Serial.read();
      ledb.setValue(colour); 
      //EEPROM.write(3, colour);
    }
  }
}

VB Code:

Public Class frmMain

    Dim oCOM As New System.IO.Ports.SerialPort


    Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        '//use the settings in the config file to set up the com port object

        Try
            oCOM.BaudRate = CInt(My.Settings.baudrate)
            oCOM.DataBits = CInt(My.Settings.databits)
            oCOM.Parity = CType(My.Settings.parity, IO.Ports.Parity)
            oCOM.StopBits = CType(My.Settings.stopbit, IO.Ports.StopBits)

            '//added her for always open
            oCOM.Open()

        Catch ex As Exception
            MessageBox.Show(ex.ToString, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub

    Private Sub btnSend0_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend0.Click
        '//button click event calls the routine below named SendComPortValue, and passes the string value to it
        SendComPortValue("1")
        SendComPortValue("0")
        SendComPortValue("2")
        SendComPortValue("0")
        SendComPortValue("3")
        SendComPortValue("0")

    End Sub

    Private Sub btnSend1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend1.Click
        '//button click event calls the routine below named SendComPortValue, and passes the string value to it
        SendComPortValue("1")
        SendComPortValue("255")
        SendComPortValue("2")
        SendComPortValue("255")
        SendComPortValue("3")
        SendComPortValue("255")
    End Sub

    '...add button events here



    Private Sub SendComPortValue(ByVal sValueToSend As String)

        '// reusable code for sending values over the com port

        Try
            'oCOM.Open()

            oCOM.Write(sValueToSend)

            'oCOM.Close()

        Catch ex As Exception
            MessageBox.Show(ex.ToString, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    End Sub


    Private Sub frmMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        '//make sure we close the com port when the app is closing
        If oCOM.IsOpen = True Then
            oCOM.Close()
        End If

        oCOM.Dispose()
    End Sub


End Class

Hi again,

There are two main things that are causing the problem:

  1. Timing issues in the Arduino sketch. Adding a delay between reading the serial bytes fixes this
  2. You are sending Strings from your VB code. Sending bytes will fix this

A few other minor things that you should be aware of:

  • When using if (Serial.available()) in an Arduino sketch you should use if(Serial.available() > 0) to account for no serial available actually returning a value of -1 which could cause a 'true' even when no serial data is available
  • In the Arduino sketch its a good idea to create variables of the type that the code expects. Using the LED.h library and the led.setvalue() command you should use a byte variable between the brackets. It would probably work with an integer but best to be on the safe side. So it'd be a good idea to use byte colour instead of int colour
  • Read your serial data outside any conditional statements. If for any reason none of the conditions were met the serial buffer would still have the 'colour' data in it the next time through the loop
  • In VB code to send byte values (which is what you want to do) you use an array of bytes (in the code below i've called this sendBuffer but you could call it anything you like.

Anyway... I've included some code below that does work...

Arduino Sketch

#include <EEPROM.h> //  http://www.arduino.cc/en/Reference/EEPROM
#include <LED.h>    //  http://www.arduino.cc/playground/Code/LED

LED ledboot_ok = LED(13);//declare digital pin 13 as the boot ok LED.
LED ledr = LED(11);//declare digital pin 11 as a Red LED's.
LED ledb = LED(10);//declare digital pin 10 as a Blue LED's.
LED ledg = LED(9); //declare digital pin 9 as a Green LED's.
// Changed these two variables to bytes instead of integers
byte com;
byte colour;

void setup()
{
  Serial.begin(9600); // opens the com port and sets it at 9600 baud
  //ledr.setValue(EEPROM.read(1)), ledg.setValue(EEPROM.read(2)), ledb.setValue(EEPROM.read(3)); // sets LEDs and fans to previous settings before it was reset/turned off.
  ledboot_ok.on(); // Turns boot_ok LED on
}

void loop()
{
  // changed (Serial.available()) to (Serial.available() > 0)
  if (Serial.available() > 0)
  {
    com = Serial.read();
    delay(50);
    colour = Serial.read();

    // This is for the red LEDs
    if (com = 1) {
      ledr.setValue(colour);
      //EEPROM.write(1, colour);
    }
    // This is for the green LEDs
    if (com = 2) {
      ledg.setValue(colour);
      //EEPROM.write(2, colour);
    }
    // This is for the blue LEDs
    if (com = 3) {
      ledb.setValue(colour);
      //EEPROM.write(3, colour);
    }
  }
}

Visual Basic code

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        With SerialPort1
            .PortName = "COM2"
            .BaudRate = 9600
        End With

        Try
            SerialPort1.Open()
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        Try
            If (SerialPort1.IsOpen()) Then
                SerialPort1.Close()
            End If
        Catch ex As Exception

        End Try
    End Sub

    Private Sub btnAllOff_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAllOff.Click
        SendComPortValue(1, 0)
        SendComPortValue(2, 0)
        SendComPortValue(3, 0)
    End Sub

    Private Sub btnAllOnFull_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAllOnFull.Click
        SendComPortValue(1, 255)
        SendComPortValue(2, 255)
        SendComPortValue(3, 255)
    End Sub

    Private Sub SendComPortValue(ByVal colour As Byte, ByVal PWMvalue As Byte)
        Dim sendBuffer() As Byte = {0, 0}
        sendBuffer(0) = colour
        sendBuffer(1) = PWMvalue

        Try
            SerialPort1.Write(sendBuffer, 0, 2)
        Catch ex As Exception

        End Try
    End Sub

End Class

Hope this helps. Good luck with the rest of it.

Andrew Craigie

Would you be able to send the VB stuff in a zip folder via email? i cant get it to debug :frowning:

Hi,

Did you create buttons on your form with the same names I used?

You can download the Visual Basic 2008 project I tested the code in here:

http://www.acraigie.com/programming/firmatavb/downloads/Du_z.zip

I'm not sure what version of Visual Basic you are using but you may not be able to open it in an Express version.

If you can't then work your way systematically through the debug errors and you should get it to work (check the button names first).

Cheers.

Andrew Craigie.

I got mine working like this :
VB code

 Public Class Form1
    Dim counter As Integer
    Dim read As Byte

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        SerialPort1.Open()
        SerialPort1.DtrEnable = True
        SerialPort1.DtrEnable = False
        Threading.Thread.Sleep(10)
        SerialPort1.DtrEnable = True
        Timer1.Start()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        counter = counter + 1
        read = SerialPort1.ReadByte
        '# 0'
        If read = 48 Then
            Button1.BackColor = Color.Red
        End If
        '# 1'
        If read = 49 Then
            Button1.BackColor = Color.Yellow
        End If
        '# 2'
        If read = 50 Then
            Button1.BackColor = Color.Lime
        End If
        If read = 48 Then
            TextBox1.Text = "0"
        End If
        If read = 49 Then
            TextBox1.Text = "1"
        End If
        If read = 50 Then
            TextBox1.Text = "2"
        End If
        If counter = 3 Then
            Call reset_arduino()
        End If
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Timer1.Stop()
        SerialPort1.DtrEnable = True
        SerialPort1.DtrEnable = False
        Threading.Thread.Sleep(10)
        SerialPort1.DtrEnable = True
        SerialPort1.DiscardInBuffer()
        Timer1.Start()
    End Sub
    Private Sub reset_arduino()
        Timer1.Stop()
        SerialPort1.DtrEnable = True
        SerialPort1.DtrEnable = False
        Threading.Thread.Sleep(10)
        SerialPort1.DtrEnable = True
        SerialPort1.Close()
        Threading.Thread.Sleep(10)
        SerialPort1.Open()
        SerialPort1.DiscardInBuffer()
        Timer1.Start()
    End Sub

Arduino code :

 void setup(){
  Serial.begin(9600);
}

void loop(){
  Serial.println("0");
  delay(100);
  Serial.println("1");
  delay(100);
  Serial.println("2");
  delay(100);
}

That will change the colour of the button on form1 by the arduino sending out 0,1,2.
Hope that helped :slight_smile:
uberdum05

@ Andrew

I changed the names of the buttons, it had more problems that that though. thank you for the download.

Edit: IT WORKS!!!! thank you so much

@uber

thanks mate

HI Andrew,
I am using your firmata VB code to control a simple remote control car.
I am trying to use the FirmataVB1.DigitalPinWrite command so what value would I have to use for the on state and the off state.And what are the pin numbers i can use?

Its like FirmataVB1.DigitalWrite(PinNumber,value)
Pin NUmber can be 0-12
what are the values for the keyword 'value' for on and off? :o

Hi jith,

In code you'd pass the value 1 for on and 0 (digit zero) for off.

Regards.

Thank you for that quick reply andrew.

Lets say if i want to use just the digitalpinwrite function,should i include the firmata.dll or digitalpincontrol.dll .which file should i include in the program.?

I get this error when i try to use it.
I have changed the properties of the firmata component in design view to COM4 and baud rate 57600 which works for the sample application from your website.

I think i have to define a method to open the COM port,but dont know how.

Can you tell me what are the components that i need to include to use the FirmataVB1.digitalpinwrite(Pin number value) option?

I have included only the firmata.dll as mentioned in your site.Nothing else.

Here is the error

Problem with digitalWrite
System.InvalidOperationException:The port is closed.
at System.IO.Ports.SerialPort.Write(Byte[] buffer,Int32 offset,Int32 count) at Firmata.FirmataVB.DigitalWrite(Int32 pin,Int32 value)

Hi jith,

Without looking at your entire code and knowing exactly how you've wired up your application I can't really help.

My only suggestion is to download the sample applications and work through these until you have a thorough understanding of how they work. In essence you need to include the FirmataVB.net component, create code to establish a COM link (see how this is done in the sample apps - the non 'extended' one should be simpler to follow) and then use code to send messages to the DigitalPin command. The DigitalPinControl component is just a handy way to add the visual functionality to your project. You can simply use the FirmataVB1.DigitalPinWrite as you have been doing in your own code instead.

Hope this helps.

Regards

Andrew Craigie

Hi Andrew,
Thank you.Now its working.I just had to include firmataVB1.connect(COM4,57600) to use the functionality of digital pin write.
And i have included the firmatavb.dll component in the design view.

What i was trying to do was to create a user interface a rc car using the arrow keys in my project.The rc car source code form JBprojects.net was using the parallel port but i needed the usb port functionality to make it work with my laptop which doesnt have a parallel port.

Now its working.
:slight_smile: :slight_smile: