Click here to Skip to main content
Click here to Skip to main content

Vehicle Accessory Computer Interface

, 26 Feb 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
A simple system to control your vehicle accessories via car PC

Introduction

The following document will provide information to develop your own VACI (Vehicle Accessory Computer Interface). What I have done is rather simple, however it took about 3 weeks of planning, programming and debugging. The wow factor on this interface is awesome; everyone that has seen/used the system wants one in their car. The system can also be modified to automate accessories.

VACI.jpg

Specifications

  • 2X RGB PWM Channels
  • 8X General Purpose Outputs
  • Support for 5 Channel AV switch. (7 Momentary Outputs)
  • RS232 Communication

Requirements

  • Software
    • Proton PicBasic Compiler
    • Serial Bootloader (Preferable)
    • VB.NET
    • HyperTerminal
  • Hardware
    • PC
    • Pic16F877A
    • PicAllw Programmer (only needed if you do not have a Serial Bootloader on your PIC)
    • Olimex PIC-P40 Development board (20Mhz)
    • 3X ULN2803 Darlington arrays
    • Some 1,10,100uF capacitors to reduce noise.
    • RS232 Cable
  • Tools
    • Soldering Iron (required for ULN2803 and capacitors on Olimex P-40 Development Board)
    • Cutters
    • Oscilloscope (if you have one)

Schematic

vaci_-_Schematic.jpg - click to enlarge image

If you have an Olimex PIC-40 Development board, you shouldn't need a schematic. If you don't, then you only need to build a stable 5V regulator to power the circuit and a RS232 logic level converter so that you can connect the serial of your computer to the serial of the microcontroller. The other important thing is to have all your outputs connected to a ULN2803 Darlington Array IC and remember that the maximum load per output should not exceed 60mA. The ULN2803 is a sinking driver, so you are able to drive your 12V relays from 12VDC. I have also uploaded the musltisim and ultiboard schematic and PCB design files, use them at your own risk. I have not tested the ultiboard design and will not accept any responsibility for it.

My Prototype Hardware

05092010575.jpg

05092010580.jpg

Using the Code

How the RGB software PWM Works

In a nutshell, the RGB software PWM works through an infinite loop with a counter which resets after 255 (one Byte). Each color byte is then compared to the clock, if it is less than the clock, the output is set high. If the color byte is greater than the clock byte, the output is set to low. The color bytes are then changed through a serial data received interrupt.

I then placed the AV switch functions and General Purpose outputs, where the counter resets after reaching 255.

Proton PicBasic Code

'****************************************************************
'* Name : SmartJeep.BAS *
'* Author : Marco van der Merwe *
'* Notice : Copyright (c) 2010 *
'* : All Rights Reserved *
'* Date : 8/21/2010 *
'* Version : 1.0 *
'* Notes : Test app for serial comms & RGB Controll *
'* : *
'****************************************************************


' PIC16F877 Pinout

'                -----------------
'         MCLR -|1      |_|     40|-
'        AvSAT -|2              39|-
'        AvDVD -|3              38|- Interior Blue
'       AvCaTV -|4              37|- Interior Green
'        AvVCR -|5              36|- Interior Red
'        AvAux -|6       P      35|- Exterior Blue
'      Av1/Av2 -|7       I      34|- Exterior Green
'       Av PWR -|8       C      33|- Exterior Red
'              -|9       1      32|- Vdd (5V)
'              -|10      6      31|- Vss (0V)
'     Vdd (5V) -|11      F      30|- GPIO 7
'      Vss(0V) -|12      8      29|- GPIO 6
'  Xtal(20Mhz) -|13      7      28|- GPIO 5
'  Xtal(20Mhz) -|14      7      27|- GPIO 4
'              -|15      A      26|- RS232(Rx)
'              -|16             25|- RS232(Tx)
'              -|17             24|-
'              -|18             23|-
'       GPIO 0 -|19             22|- GPIO 3
'       GPIO 1 -|20             21|- GPIO 2
'                -----------------

Device = 16F877A ' Select PIC16F877A for Destination Device
Declare Bootloader = On ' Notify Compiler of Bootloader
Config HS_OSC ' Make use of High Speed Oscilator
Xtal = 20 ' Use 20Mhz Xtal
Optimiser_Level = 1 ' Simple optimisation
Dead_Code_Remove = On ' Remove any redundant code

'Configure Hardware Serial Port

Hserial_Baud = 9600 ' Set baud rate to 9600
Hserial_RCSTA = %10010000 ' Enable serial port and continuous receive
Hserial_Clear = On ' Optionally clear the buffer before receiving

'Disable Analog Ports
All_Digital true

'Serial Related Variables
Dim D_Index As Byte ' Char Rx index
Dim D_Byte[12] As Byte ' Rx buffer
Symbol RCIF = PIR1.5 ' Alias RCIF (USART Receive Interrupt Flag)

'Switch Vars
Dim AVclk As Byte
Dim AVMode As Byte
Dim GPO As Byte

'RGB Variables
Dim clk As Byte ' clk Counter

'Adjustable Variables
Dim ERGB[3] As Byte 'Exterior Red, Green, Blue
Dim EBSO[3] As Byte 'Exterior Brightness, Speed, Option
Dim IRGB[3] As Byte 'Interior Red, Green, Blue
Dim IBSO[3] As Byte 'Interior Brightness, Speed, Option
'Important Note:
'EBSO & IBSO have not been fully implemented,
'they are put in place to support RGB effects and transitions

'------------------------------------------------------------------------------------
' Initialise variables
DelayMS 500 ' Wait for the power supply to stabilise
INTCON = %11000000 ' Enable interrupts
On_Hardware_Interrupt GoTo SerialIn ' Declare hardware interrupt handler routine
PIE1.5 = 1 ' Enable interrupt on USART
D_Index = 0 ' Initialise index as 0
clk = 0 ' Initialise Clk as 0
AVclk = 0 ' Initialise AVclk as 0
AVMode = 0 ' Initialise AVMode as 0
GPO = 0 ' Initialise GPO as 0
TRISB = %11000000 ' Set 0~5 on PortB as output for R1G1B1 R2G2B1
TRISA = %11000000 ' Set 0~6 on PortA as output for AV Switch
TRISE = %11111110 ' Set 0 on portE as output for AV switch
TRISD = %00000000 ' Set 0~7 on PortD as output for General outputs

'Set all outputs to Low
PORTA = 0
PORTB = 0
PORTD = 0

Clear D_Byte ' Initialise D_Byte as 0
Clear ERGB
Clear EBSO
Clear IRGB
Clear IBSO
'------------------------------------------------------------------------------------
' Main Program
Loop:
   ' Do the RGB PWM
   If clk < ERGB[0] Then
      Low PORTB.0
   Else
      High PORTB.0
   EndIf
   If clk < ERGB[1] Then
      Low PORTB.1
   Else
      High PORTB.1
   EndIf
   If clk < ERGB[2] Then
      Low PORTB.2
   Else
      High PORTB.2
   EndIf
   If clk < IRGB[0] Then
      Low PORTB.3
   Else
      High PORTB.3
   EndIf
   If clk < IRGB[1] Then
      Low PORTB.4
   Else
      High PORTB.4
   EndIf
   If clk < IRGB[2] Then
      Low PORTB.5
   Else
      High PORTB.5
   EndIf

   Inc clk 'Increment the clock counter
   If clk >= 255 Then '
      clk = 0 ' Reset clk
      Inc AVclk ' Increment AVclk
      If AVMode > 0 Then ' Check if AVMode has changed
         Select Case AVMode
            Case <=32
               PORTA = AVMode
            Case 64
               High PORTE.0
         End Select
         AVMode = 0
         AVclk = 0 ' Reset AVclk
      EndIf
      PORTD = GPO
      If AVclk >= 32 Then ' On Duration
         PORTA = 0 ' Switch off
         PORTE = 0
         AVclk = 0 ' Reset AVclk
      EndIf
   EndIf

   GoTo Loop

'-----------------------------------------------------------------------------------
' Interrupt handler
SerialIn: ' Buffer the character received
   Int_Sub_Start
INT#STARTH:
  Context Save
RECHECK:
   If D_Index > 10 Then GoSub clr_Buff ' Max Index = 12

   HRSIn D_Byte[D_Index]
   HRSOut D_Byte[D_Index]

Inc D_Index ' Increment Buffer_Index

Select D_Byte[0]
      Case "A"
         If D_Index > 1 Then
            AVMode = D_Byte[1]
            GoSub clr_Buff
         EndIf
      Case "G"
         If D_Index > 1 Then
            GPO = D_Byte[1]
            GoSub clr_Buff
         EndIf
      Case "E"
         If D_Index > 6 Then
            ERGB[0] = D_Byte[1]
            ERGB[1] = D_Byte[2]
            ERGB[2] = D_Byte[3]
            EBSO[0] = D_Byte[4]
            EBSO[1] = D_Byte[5]
            EBSO[2] = D_Byte[6]
            GoSub clr_Buff
         EndIf

      Case "I"
         If D_Index > 6 Then
            IRGB[0] = D_Byte[1]
            IRGB[1] = D_Byte[2]
            IRGB[2] = D_Byte[3]
            IBSO[0] = D_Byte[4]
            IBSO[1] = D_Byte[5]
            IBSO[2] = D_Byte[6]
            GoSub clr_Buff
         EndIf

      Case Else
         GoSub clr_Buff
   End Select

   If RCIF = 1 Then RECHECK ' Check for another character while we're here
   GoTo INT_RETURN ' Return to program
   clr_Buff:
   D_Index = 0 ' Else Index 0
   Clear D_Byte ' Clear String
   Return
   INT#ENDH:
   INT_RETURN:
   Context Restore
Int_Sub_End

Computer Interface Module

The Interface module then takes care of all the communication between the user interface and the microcontroller. Simply insert the following module in your VB.NET project.

VB.NET Module

Imports System
Imports System.IO.Ports 'Support for serial Port control
Imports System.Drawing 'Support for color type

''' <summary>
''' Hardware communication module for VACI.
''' Created by Marco van der Merwe (7 September 2010)
''' </summary>
Module VACI
   WithEvents COMS As New SerialPort("Com1", 9600, Parity.None, 8, StopBits.One)
   '<<<< Serial Port >>>>
   ''' <summary>
   ''' Open Communication session
   ''' </summary>
   Sub Open()
      If COMS.IsOpen = False Then
         COMS.Encoding = System.Text.Encoding.Default
         COMS.Open() ' open the serial ComPort1
      End If
   End Sub

   ''' <summary>
   ''' Close Communication session
   ''' </summary>
   Sub Close()
     If COMS.IsOpen = True Then
        COMS.Close()
     End If
   End Sub

   Private Sub COMS_DataReceived(ByVal sender As Object, _
	ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
		Handles COMS.DataReceived
      Dim MyStr As String
      MyStr = COMS.ReadExisting
   End Sub

   '<<<< Hardware I/O Controll >>>>

   ''' <summary>
   ''' Lighting Effect Control
   ''' </summary>
   ''' <remarks></remarks>
   Class GlowFx

       ''' <summary>
       ''' Sets Exterior RGB Glow as Color
       ''' </summary>
       ''' <value></value>
       ''' <remarks></remarks>
       Shared WriteOnly Property Exterior() As Color
          Set(ByVal iColor As Color)
             If COMS.IsOpen = True Then
                 'Note that "000" is reserved for RGB Transitions and Effects
                 COMS.Write("E" & Chr(iColor.R) & Chr(iColor.G) _
			& Chr(iColor.B) & "000" & Chr(234))
             End If
          End Set
       End Property

       ''' <summary>
       ''' Sets Interior RGB Glow as Color
       ''' </summary>
       ''' <value></value>
       ''' <remarks></remarks>
       Shared WriteOnly Property Interior() As Color
          Set(ByVal iColor As Color)
             If COMS.IsOpen = True Then
                 'Note that "000" is reserved for RGB Transitions and Effects
                COMS.Write("I" & Chr(iColor.R) & Chr(iColor.G) _
			& Chr(iColor.B) & "000" & Chr(234))
             End If
          End Set
       End Property
   End Class

    ''' <summary>
    ''' General I/O Control
    ''' </summary>
    ''' <remarks></remarks>
    Class GeneralIO
       Private Shared Switch(0 To 7) As Boolean
       Shared WriteOnly Property G0() As Boolean
         Set(ByVal G0 As Boolean)
            Switch(0) = G0
            SetGeneralIO()
         End Set
      End Property

      Shared WriteOnly Property G1() As Boolean
         Set(ByVal G1 As Boolean)
            Switch(1) = G1
            SetGeneralIO()
         End Set
      End Property

      Shared WriteOnly Property G2() As Boolean
         Set(ByVal G2 As Boolean)
            Switch(2) = G2
            SetGeneralIO()
         End Set
      End Property

      Shared WriteOnly Property G3() As Boolean
         Set(ByVal G3 As Boolean)
            Switch(3) = G3
            SetGeneralIO()
         End Set
      End Property

      Shared WriteOnly Property G4() As Boolean
         Set(ByVal G4 As Boolean)
            Switch(4) = G4
            SetGeneralIO()
         End Set
      End Property

       Shared WriteOnly Property G5() As Boolean
          Set(ByVal G5 As Boolean)
             Switch(5) = G5
             SetGeneralIO()
          End Set
      End Property

       Shared WriteOnly Property G6() As Boolean
          Set(ByVal G6 As Boolean)
             Switch(6) = G6
             SetGeneralIO()
          End Set
      End Property

       Shared WriteOnly Property G7() As Boolean
           Set(ByVal G7 As Boolean)
              Switch(7) = G7
              SetGeneralIO()
           End Set
      End Property

       Private Shared Sub SetGeneralIO()
          Dim GByte As Byte = 0
          GByte = IIf(Switch(0), 1, 0) + IIf(Switch(1), 2, 0) + _
		IIf(Switch(2), 4, 0) + IIf(Switch(3), 8, 0) + _
          IIf(Switch(4), 16, 0) + IIf(Switch(5), 32, 0) + _
		IIf(Switch(6), 64, 0) + IIf(Switch(7), 128, 0)
          If COMS.IsOpen = True Then
             COMS.Write("G" & Chr(GByte) & Chr(234))
          End If
       End Sub
   End Class

   ''' <summary>
   ''' AV Switch Control
   ''' </summary>
   ''' <remarks></remarks>
   Class AVSwitch

       ''' <summary>
       ''' Toggles AV Switch Power
       ''' </summary>
       ''' <remarks></remarks>
       Shared Sub TogglePWR()
          If COMS.IsOpen = True Then
             COMS.Write("A" & Chr(64) & Chr(234))
          End If
       End Sub

      ''' <summary>
      ''' Toggles AV Switch Output Channel
      ''' </summary>
      ''' <remarks></remarks>
      Shared Sub ToggleAV()
         If COMS.IsOpen = True Then
            COMS.Write("A" & Chr(32) & Chr(234))
         End If
      End Sub

      ''' <summary>
      ''' Sets AV Switch Channel: 1 through 5
      ''' </summary>
      ''' <param name="AVChan"></param>
      ''' <remarks></remarks>
      Shared Sub SetAVChan(ByVal AVChan As Byte)
         If COMS.IsOpen = True Then
            Select Case AVChan
               Case 1
                  COMS.Write("A" & Chr(1) & Chr(234))
               Case 2
                  COMS.Write("A" & Chr(2) & Chr(234))
               Case 3
                  COMS.Write("A" & Chr(4) & Chr(234))
               Case 4
                  COMS.Write("A" & Chr(8) & Chr(234))
               Case 5
                  COMS.Write("A" & Chr(16) & Chr(234))
            End Select
         End If
      End Sub

   End Class

End Module

To initialize the communication, simply place the following code in your project, only remember to close the serial communication on exit. If you don't disable the serial communication when you exit the application, there will be a problem initializing serial port if the application is reopened.

Private Sub Form1_Load(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles MyBase.Load
   'Start Serial Communication with VACI
   VACI.Open()
End Sub

Private Sub Form1_FormClosing(ByVal sender As Object, _
	ByVal e As System.Windows.Forms.FormClosingEventArgs) _
		Handles Me.FormClosing
   'End Serial Communication with VACI
   VACI.Close()
End Sub

To toggle the power of the AV switch, use the following code:

Private Sub Button1_Click(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles Button1.Click
  VACI.AVSwitch.TogglePWR()End Sub

To set the AV switch channel, use the following code:

Private Sub Button1_Click(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles Button1.Click
  VACI.AVSwitch.SetAVChan(1)
End Sub

The following code is used to set the General Purpose outputs G0 through G7, TRUE is for on and FALSE for off.

Private Sub Button1_Click(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles Button1.Click
  VACI.GeneralIO.G3 = True
End Sub

The following code is used to set the RGB Glow Channel 1 as color:

Private Sub Button1_Click(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles Button1.Click
  VACI.GlowFx.Exterior = Color.GreenYellow
End Sub

The following code is used to set the RGB Glow Channel 2 as color:

Private Sub Button1_Click(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles Button1.Click
   VACI.GlowFx.Interior = Color.OrangeRed
End Sub

Test.

Points of Interest

I have been programming Pic16Fs for over 7 years, and I got bored of manually flipping switches on my jeep. So I decided to combine my experience of programming and hardware to develop this application to ease my accessory usage in my jeep.

My aim was to integrate all my accessories into a central system, I was given a Lilliput PC745 as a gift and decided to use that. In my solution, I have used the PC745’s serial port to communicate with the PIC 16F877A.

The most complex problem that had to be solved is the 6 PWM (Pulse Width Modulation) channels that were needed to run the two RGB LED channels. The 16F877A only has two, so I opted for a type of software PWM. This meant that the first thing I had to get working was the software PWM along with the serial communication.

This took several attempts with different resolutions, refresh rates and so on. I experimented with different clock frequencies. Finally, it came to an 8bit resolution, with an unknown refresh rate. The best solution with the least amount of flicker came to be by doing an infinite loop with no delays and turning each of the pins on/off for the desired time.

The next task was to fit the General Purpose output pins in this infinite loop without delay, or else the RGB glow would flicker. The best way to do that is simply assign an entire port at the same time through one byte. So the PC would have to generate a character for the desired pins to be switched on individually. Each bit in the byte is a pin on the microcontroller which makes life a bit easier.

I then had an off-the-shelf AV switch to select my AV input channels; it switches by momentary push button. So I combined PortE.0 with PortA, as PortA only has 6 pins and I needed 7. The tricky part was to create a momentary switch without delaying PWM channels. So to do this, I stuck my code in at the end of the For Loop that refreshes the RGB channels. So that it switches high at the end of the update, then waits for 32 RGB refresh cycles before clearing the port. This can be modified very easily to be used as General Purpose Outputs.

History

  • First working version - 22/09/2010

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

bigbro_1985
Engineer
Qatar Qatar
My love for imagining, designing and creating just about anything REAL or VIRTUAL has lead me on this path. Whether it be 1’s and 0’s, soldering an IC to a PCB or getting under the car just to get my hands dirty, I like to do it DIY.
Life is a journey, and it’s all about learning and creating…
 
Some Achievements in my life:
• Founder of the Doha College Robotics Club
• President and founder of the CNA-Q Robotics Club
• Developed Fly-By-Wire Over Ethernet (FBWOE) for boats.
• Telecommunication Engineering Technology Diploma
• X10 Home Automation system as part of a Green Home project
Developed a Vehicle Accessory Computer Interface (VACI)
• Autonomos Turtle Monitoring Robot
Virtual Autonomous Remote Presence (VARP)
• Electrical Engineering Degree from Purdue
• Various Industrial Automation projects ranging from manufacturing car parts to plastics, shaving cream and even ice-cream. I have worked with various robotic systems, VFD's, HMI's, PLCs, industrial networking/data collection systems, and Machine Vision systems.

Comments and Discussions

 
GeneralGood Stuff - 5 from me PinmemberK-Sid14-Mar-11 4:37 
GeneralRe: Good Stuff - 5 from me Pinmemberbigbro_198516-Mar-11 4:32 
GeneralGreat stuff... just another approach PinmemberThe Monz8-Feb-11 1:10 
GeneralRe: Great stuff... just another approach Pinmemberbigbro_19858-Feb-11 7:59 
GeneralRe: Great stuff... just another approach PinmemberInstallstogo15-Jul-12 20:02 
SuggestionRe: Great stuff... just another approach [modified] Pinmemberbigbro_198516-Jul-12 2:16 
GeneralMy vote of 5 PinmemberJF201525-Jan-11 19:50 
GeneralRe: My vote of 5 Pinmemberbigbro_198526-Jan-11 7:24 
Generalgood one - have 5 PinmemberPranay Rana24-Jan-11 21:49 
GeneralRe: good one - have 5 Pinmemberbigbro_198524-Jan-11 21:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 26 Feb 2011
Article Copyright 2011 by bigbro_1985
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid