B4J Tutorial [RPi Model 3] Sunfounder Super Kit v2.0

I have just purchased this kit and have started to go through the examples. In an effort to help others like me with little or no knowledge of how to port the examples to B4J, I thought it might be helpful if I post my code for each example.

The wiring for each example is as described in the handbook or online here.

libraries required: jPi4j, JavaObject, Core

I hope it helps someone.

Edit: please note, I post this code as it has worked for me. That does not mean it is the easiest way to code. I am still learning and that is fun.
 
Last edited:

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 1: Blinking LED

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
   Private timer1 As Timer
   Private controller As GpioController
   Private pin0 As GpioPinDigitalOutput
     
End Sub

Sub AppStart (Args() As String)
   controller.Initialize
   pin0.Initialize(0, True)
  
   timer1.Initialize("timer1", 1000)
   timer1.Enabled = True
  
   StartMessageLoop
End Sub

Private Sub Timer1_Tick
  
   pin0.State = Not(pin0.State)
  
   Log("Current State: " & pin0.State)
End Sub
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 2 Controlling an LED by a Button (switch)

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
  
   Private controller As GpioController
   Private pin0 As GpioPinDigitalOutput
   Private pin1 As GpioPinDigitalInput  
End Sub

Sub AppStart (Args() As String)
   controller.Initialize
   pin0.Initialize(0, False)
   pin1.Initialize("SwitchValue",1)
   pin1.SetPinPullResistance("PULL_UP")        ' Will not work without this line!
   StartMessageLoop
End Sub

Sub SwitchValue_StateChange(State As Boolean)
    Log("Switch: " & State)
    pin0.State = Not(pin0.State)
End Sub

Edit: Code updated, sorry wrong code.
 
Last edited:

Mark Read

Well-Known Member
Licensed User
Longtime User
Traffic Light (not in handbook), a modified version of Erel's tutorial here.

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
   Type State (Duration As Int, Red As Boolean, Yellow As Boolean, Green As Boolean)
   Private timer1 As Timer
   Private controller As GpioController
   Private pinRed, pinYellow, pinGreen As GpioPinDigitalOutput
   Private states As List
   Private currentStateIndex As Int
End Sub

Sub AppStart (Args() As String)
   controller.Initialize
   pinRed.Initialize(27, False)
   pinYellow.Initialize(28, False)
   pinGreen.Initialize(29, False)
   states.Initialize
   states.Add(CreateState(8000, False, True, True)) 'only red
   states.Add(CreateState(4000, False, False, True)) 'red + yellow
   states.Add(CreateState(8000, True, True, False)) 'only green
   states.Add(CreateState(4000, True, False, False)) 'green + yellow
   Log(states)
   timer1.Initialize("timer1", 1000)
   timer1.Enabled = True
   currentStateIndex = -1 'it will be incremented in Timer1_Tick
   Timer1_Tick 'start with the first state
   StartMessageLoop
End Sub

Private Sub Timer1_Tick
   currentStateIndex = (currentStateIndex + 1) mod states.Size
   Dim st As State = states.Get(currentStateIndex)
   pinRed.State = st.Red
   pinYellow.State = st.Yellow
   pinGreen.State = st.Green
   timer1.Interval = st.Duration
   Log("Current State: " & currentStateIndex)
End Sub

Note: I had to reverse the logic in defining the states in lines 22 to 25. I do not know why - sorry.
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 4 Breathing LED

This one had me confused for a long time but I managed in the end.

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
  
    Private controller As GpioController
    Private timer1 As Timer
    Private val, inc As Int 
End Sub

Sub AppStart (Args() As String)
    controller.Initialize
    timer1.Initialize("timer1",100)

    ' Initialise GPIO Pin1 on RPi3 with a starting value of 0 (off) and a range of 100 (off to on)
    Dim jo As JavaObject
    jo.InitializeStatic("com.pi4j.wiringpi.SoftPwm")
    jo.RunMethod("softPwmCreate", Array (1, 0, 100))
   
    val=0
    inc=5
    timer1.Enabled=True
      
    StartMessageLoop
End Sub

Sub timer1_Tick
    val=val+inc
    If val=100 Then inc=inc*-1
    If val=0 Then inc=inc*-1
   
    ' Send val to pin to control brightness
    Dim jo As JavaObject
    jo.InitializeStatic("com.pi4j.wiringpi.SoftPwm")
    jo.RunMethod("softPwmWrite", Array (1, val))
End Sub
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 5 RGB LED

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
       Type State (Red As Int, Green As Int, Blue As Int)
    Private controller As GpioController
    Private timer1 As Timer
    Private states As List
    Private currentStateIndex As Int 
End Sub

Sub AppStart (Args() As String)
    controller.Initialize
    timer1.Initialize("timer1",1000)

    ' Initialise GPIO Pin1 to pin3 on RPi3 with a starting value of 0 (off) and a range of 100 (off to on)
    Dim jo As JavaObject
    jo.InitializeStatic("com.pi4j.wiringpi.SoftPwm")
    jo.RunMethod("softPwmCreate", Array (0, 0, 100))
    jo.RunMethod("softPwmCreate", Array (1, 0, 100))
    jo.RunMethod("softPwmCreate", Array (2, 0, 100))
   
    ' Create a list of states to apply. Values can lie between 0 and 100
    states.Initialize
    states.Add(CreateState(100,0,0)) 'only red
    states.Add(CreateState(0,100,0)) 'only green
    states.Add(CreateState(0,0,100)) 'only blue
    states.Add(CreateState(25,25,25)) 'all mixed
    states.Add(CreateState(50,25,25)) 'all mixed
    states.Add(CreateState(75,25,25)) 'all mixed
    states.Add(CreateState(25,25,25)) 'all mixed
    states.Add(CreateState(25,50,25)) 'all mixed
    states.Add(CreateState(25,75,25)) 'all mixed
    states.Add(CreateState(25,25,50)) 'all mixed
    states.Add(CreateState(25,25,75)) 'all mixed
   
    timer1.Enabled=True
      
    StartMessageLoop
End Sub

Sub timer1_Tick
    currentStateIndex = (currentStateIndex + 1) mod states.Size
    Dim st As State = states.Get(currentStateIndex)
       
    'Send val To pin To control brightness and color
    Dim jo As JavaObject
    jo.InitializeStatic("com.pi4j.wiringpi.SoftPwm")
    jo.RunMethod("softPwmWrite", Array (0, st.Red))
    jo.RunMethod("softPwmWrite", Array (1, st.Green))
    jo.RunMethod("softPwmWrite", Array (2, st.Blue))
End Sub

Private Sub CreateState(Red As Int, Green As Int, Blue As Int) As State
   Dim st As State
   st.Initialize
   st.Red = Red
   st.Green = Green
   st.Blue = Blue
   Return st
End Sub
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 6 Buzzer

The same code as in post #2 above. The buzzer is active so it only goes on and off.
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 7 How to Drive a DC Motor

Coming later as the circuit in handbook and online do not match. An external power supply is also required (not included).

After contacting Sunfounder, both circuits are valid. I have used the simple circuit as detailed on the homepage. My external power supply was a multivolt system set to 7.5V.

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
 
    Private controller As GpioController
    Private pin0 As GpioPinDigitalOutput        'CW pin11
    Private pin1 As GpioPinDigitalOutput          'CCW pin12
    Private pin2 As GpioPinDigitalOutput           'Motor enable pin13
    Private timer1,timer2 As Timer
End Sub

Sub AppStart (Args() As String)
    controller.Initialize
    pin0.Initialize(0, False)
    pin1.Initialize(1, True)
    pin2.Initialize(2, False)
    timer1.Initialize("timer1",3000)            'duration of motor
    timer2.Initialize("timer2",1000)            'used to allow the motor to stop
 
    pin2.State=True                                'enable motor
    pin0.State=Not(pin0.State)
    pin1.State=Not(pin1.State)                    'start motor CW
    
      timer1.Enabled=True
 
    StartMessageLoop
End Sub

Sub timer1_Tick
    pin2.State=False                            'stop motor
    pin0.State=Not(pin0.State)
    pin1.State=Not(pin1.State)                    'reverse direction
    timer1.Enabled=False
    timer2.Enabled=True

End Sub

Sub timer2_Tick
    timer2.Enabled=False
    timer1.Enabled=True
    pin2.State=True                                'enable motor
End Sub
 
Last edited:

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 7 How to Drive a DC Motor - modified.

The circuit is the same as in post#7 but the pin 0 uses PWM control.

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
  
    Private controller As GpioController
    Private pin1 As GpioPinDigitalOutput          'CCW pin12
    Private pin2 As GpioPinDigitalOutput           'Motor enable pin13
    Private timer1,timer2 As Timer
End Sub

Sub AppStart (Args() As String)
    controller.Initialize
    pin1.Initialize(1, False)
    pin2.Initialize(2, False)
    timer1.Initialize("timer1",3000)            'duration of motor
    timer2.Initialize("timer2",1000)            'used to allow the motor to stop
  
    pin2.State=True                                'enable motor
   
    ' Initialise GPIO Pin0 on RPi3 with a starting value of 0 (off) and a range of 100 (off to on)
    Dim jo As JavaObject
    jo.InitializeStatic("com.pi4j.wiringpi.SoftPwm")
    jo.RunMethod("softPwmCreate", Array (0, 0, 100))
   
    jo.RunMethod("softPwmWrite", Array (0, 35))                    'start motor CW with 35% speed. Under 35%, the motor does not turn.
     
      timer1.Enabled=True
  
    StartMessageLoop
End Sub

Sub timer1_Tick
    pin2.State=False                            'stop motor
    timer1.Enabled=False
    timer2.Enabled=True
End Sub

Sub timer2_Tick
    timer2.Enabled=False
    timer1.Enabled=True
    pin2.State=True                                'enable motor
End Sub
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 8 Rotary Encoder

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
   Private controller As GpioController
   Private pin0 As GpioPinDigitalInput
   Private pin1 As GpioPinDigitalInput
   Private counter As Int=0
    
End Sub

Sub AppStart (Args() As String)
   controller.Initialize
   pin0.Initialize("DT",0)            ' Connection DT
   pin1.Initialize("CLK",1)            ' Connection CLK
   'Log("DT initial state is " & pin0.State & ", CLK initial state is " & pin1.State)
   Log("Counter: " & counter)
   StartMessageLoop
End Sub

Sub DT_StateChange(State As Boolean)
    If pin0.State=False And pin1.State=False Then
        counter=counter+1
        'Log("DT triggered - DT is " & pin0.State & ", CLK is " & pin1.State)
        Log("Counter: " & counter)
    End If
    If pin0.State=True And pin1.State=False Then   
        counter=counter-1
        'Log("DT triggered - DT is " & pin0.State & ", CLK is " & pin1.State)
        Log("Counter: " & counter)
    End If
End Sub

Sub CLK_StateChange(State As Boolean)
    'Log("CLK triggered - DT is " & pin0.State & ", CLK is " & pin1.State)
End Sub
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 7 How to Drive a DC Motor - modified.

Added two push buttons to turn motor on/off and reverse direction.

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
    Private controller As GpioController
    Private pin0 As GpioPinDigitalOutput                'CW pin11 GPIO 0
    Private pin1 As GpioPinDigitalOutput                  'CCW pin12 GPIO 1
    Private pin2 As GpioPinDigitalOutput                   'Motor enable pin13 GPIO 2
    Private SwitchEnable As GpioPinDigitalInput            'Motor enable switch pin 15 GPIO 3
    Private SwitchReverse As GpioPinDigitalInput        'Switch reverse direction pin 16 GPIO 4
End Sub

Sub AppStart (Args() As String)
    controller.Initialize
    pin0.Initialize(0, True)
    pin1.Initialize(1, False)                            'start direction is CW
    pin2.Initialize(2, False)                            'motor is not enabled
      
    SwitchEnable.Initialize("SwitchEnable",3)
    SwitchEnable.SetPinPullResistance("PULL_UP")
   
    SwitchReverse.Initialize("SwitchReverse",4)
    SwitchReverse.SetPinPullResistance("PULL_UP")
   
    'Press switch 1 to start and stop motor
    'Press switch 2 to change direction. motor must be restarted.    
     
    StartMessageLoop
End Sub

Sub SwitchEnable_StateChange(State As Boolean)            'pressing the switch changes state to false, releasing to true
    Log("Enable=" & State)
    If State=False Then
        pin2.State=Not(pin2.State)
        Log("Motor enabled: " & pin2.State)
    End If
End Sub

Sub SwitchReverse_StateChange(State As Boolean)
    Log("Reverse=" & State)
    If State=False Then
        pin2.State=False                                'stop motor
        pin0.State=Not(pin0.State)
        pin1.State=Not(pin1.State)
    Log("Motor reversed")
    End If
End Sub
 

Mark Read

Well-Known Member
Licensed User
Longtime User
My first attempt at using a stepper motor. As my Adafruit Hat is not compatible with B4J without a wrapper, I used the L293D chip and created my own circuit (discovered Fritzing in the process!).

It may not be nice to look at but it seems to work and brings me a huge step further in my project.

I didn't manage to get the Fritzing RPi3 to work (kept on putting the wires in the middle instead of on the GPIO), so I just made a note of the connections.

schrittmotor-pi_bb.jpg
The code:

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
   Type State (MotorOutput1 As Boolean, MotorOutput2 As Boolean, MotorOutput3 As Boolean, MotorOutput4 As Boolean)
   Private timer1 As Timer
   Private controller As GpioController
   Private mA, mC, mD, mF, MotorEnable As GpioPinDigitalOutput
   Private states As List
   Private currentStateIndex As Int
   Private CW As Boolean=True
   Private StepDelay As Int
End Sub

Sub AppStart (Args() As String)
   controller.Initialize
   MotorEnable.Initialize(0, True)
   mA.Initialize(2, True)            ' A        white        * Color coding for my motor, 6 pin *
   mC.Initialize(3, False)            ' A'    red
   mF.Initialize(4, False)            ' B     yellow
   mD.Initialize(5, True)            ' B     blue
  
   StepDelay=100
   states.Initialize
   states.Add(CreateState(True, True, False, False))
   states.Add(CreateState(False, True, True,False))
   states.Add(CreateState(False, False, True, True))
   states.Add(CreateState(True, False, False, True))
  
   'Log(states)
   timer1.Initialize("timer1", StepDelay)
   timer1.Enabled = True
  
   If CW=True Then
           currentStateIndex = states.Size 'it will be incremented in Timer1_Tick
    Else
        currentStateIndex=-1
    End If   
       
   Timer1_Tick 'start with the first state
   StartMessageLoop
End Sub

Private Sub Timer1_Tick
    If CW=True Then
           currentStateIndex=currentStateIndex-1
        If currentStateIndex=-1 Then currentStateIndex = states.Size-1
    Else
        currentStateIndex = (currentStateIndex + 1) mod states.Size
    End If

   Dim st As State = states.Get(currentStateIndex)
   mA.State = st.MotorOutput1
   mC.State = st.MotorOutput2
   mF.State = st.MotorOutput3
   mD.state = st.MotorOutput4
   'timer1.Interval = st.Duration
   'Log("Current State: " & currentStateIndex)
End Sub

Private Sub CreateState(Motor1 As Boolean, Motor2 As Boolean, Motor3 As Boolean, Motor4 As Boolean) As State
   Dim st As State
   st.Initialize
   st.MotorOutput1 = Motor1
   st.MotorOutput2 = Motor3
   st.MotorOutput3 = Motor2
   st.MotorOutput4 = Motor4
   Return st
End Sub
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 13 LCD1602 (Modified to accept scrolling text)

The methods available for the LCD are detailed here.

Wiring diagram:

LCD Scroll_bb.png


B4J Code:

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals

    Dim controller As GpioController
    Dim timer1 As Timer
    Dim lcd As JavaObject
    Dim handle As Int
    Dim MyText,ScrollingText As String
    Dim TextChar, Col As Int
End Sub

Sub AppStart (Args() As String)
    controller.Initialize

    lcd.InitializeStatic("com.pi4j.wiringpi.Lcd")
    timer1.Initialize("timer1",300)

    'int lcdInit(int rows, int cols, int bits, int rs, int strb, int d0, int d1, int d2, int d3, int d4,
    '     int d5, int d6, int d7);
    handle= lcd.RunMethod("lcdInit", Array(2,16,4,1,2,3,4,5,6,0,0,0,0))

    lcd.RunMethod("lcdClear", Array(handle))
    'lcd.RunMethod("lcdPosition", Array(handle, 0,0))
    'lcd.RunMethod("lcdPuts", Array(handle, "Test LCD on Rpi"))
    'lcd.RunMethod("lcdPosition", Array(handle, 0,1))
    'lcd.RunMethod("lcdPuts", Array(handle, "Pi4j with B4J"))


    MyText="This is scrolling text, it is quite long!"

    TextChar=0                                                            ' Start with first character in MyText
    Col=16                                                                ' Start position on LCD, scroll right to left.
    ScrollingText=MyText.SubString2(TextChar,TextChar+1)                ' Get first character of string

    timer1.Enabled=True
    StartMessageLoop        ' Comment if don't want to run continiously
End Sub


Sub timer1_Tick
    'Log("Col: " & Col & " ,TextChar: " & TextChar & " ,Scrolling Text = " & ScrollingText)

    lcd.RunMethod("lcdClear", Array(handle))                  
    lcd.RunMethod("lcdPosition", Array(handle, Col,0))                    'Horizontal scroll in row 1
    lcd.RunMethod("lcdPuts", Array(handle, ScrollingText))

    ' Stop
    If TextChar=MyText.Length Then
        timer1.Enabled=False
        ExitApplication
    End If

    If Col>0 Then                                                        'If we are not in column 1 then add more characters
        Col=Col-1
        ScrollingText=MyText.SubString2(0,16-Col)
    Else
        TextChar=TextChar+1                                                'otherwise, change the start position in substring.
        If TextChar+16<MyText.Length Then
            ScrollingText=MyText.SubString2(TextChar,TextChar+16)
        Else
            ScrollingText=MyText.SubString2(TextChar,MyText.Length)
        End If
    End If
End Sub

Thanks to KMatle for his tutorial:

https://www.b4x.com/android/forum/t...lcd-display-with-you-raspberry.60302/#content
 

Mark Read

Well-Known Member
Licensed User
Longtime User
Lesson 10 Driving LEDs by 74HC595 (Modified for two chips)

First the Fritzing Plan:

Lauflicht_bb.png


I used a 7.5V power supply and 9 LEDs (had no more room on the breadboard!).

The code follows:

B4X:
'Non-UI application (console / server application)
#Region  Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
    Private controller As GpioController
    Private dataPin As GpioPinDigitalOutput     'serial data input
    Private latchPin As GpioPinDigitalOutput     'memory clock input STCP (latch) copies inputs to outputs when toggled
    Private clockPin As GpioPinDigitalOutput     'shift register clock input SHCP
    Dim Value As Byte
    Dim pause As Int
    Private tmr As Timer
    Dim b(2) As Byte
    Dim BitOrder As Boolean=True
    b(0) = 0x01
    b(1) = 0x00
End Sub

Sub AppStart (Args() As String)
    controller.Initialize
  
    dataPin.Initialize(2, False)        'Pin 13, GPIO 2
    latchPin.Initialize(4, False)        'Pin 16, GPIO 4
    clockPin.Initialize(3, False)        'Pin 15, GPIO 3
  
    pause=200
  
    tmr.Initialize("tmr",pause)
       
    ClearLED
    MultiWrite(b)
    tmr.Enabled = True
  
    StartMessageLoop
End Sub

Sub tmr_tick
    If b(0) = -128 Then
        b(0) = 0x00
        b(1) = 0x01
    Else if b(1) = 2 Then
        b(0) = 0x01
        b(1) = 0x00
        BitOrder=Not(BitOrder)
    Else  
        b(0) = Bit.ShiftLeft(b(0),1)
        b(1) = Bit.ShiftLeft(b(1),1)
    End If
  
    Log("BitOrder is " &BitOrder)
    Log("b(0)= " & b(0))
    Log("b(1)= " & b(1))
    Log(" ")
    MultiWrite(b)
End Sub

Sub MultiWrite(ByteValue() As Byte)
    latchPin.State=False
    For i =  ByteValue.Length - 1 To 0 Step -1
       Value = ByteValue(i)  
       ShiftOut
    Next
    latchPin.State=True
End Sub

Sub ShiftOut
  Dim aa, bb, cc As Int

  If BitOrder Then
    aa = 7
    bb = 0
    cc = -1
  Else
    aa = 0
    bb = 7
    cc = 1
  End If
  For i = aa To bb Step cc
    clockPin.State=False
    If getBits(Value,i,i) = 1 Then
        dataPin.State=True
    Else
        dataPin.State=False
    End If
    clockPin.State=True
    dataPin.State=False
  Next
  clockPin.State=False
End Sub

Sub SendBit(BitState As Boolean)    'not used
    clockPin.State=False
    dataPin.State=BitState            'Set data bit
    clockPin.State=True                'set shift register clock input  
    latchPin.State=True                'Toggle latch
    latchPin.State=False
End Sub

Sub ClearLED                        'Clear two bytes
    For i=0 To 15
        SendBit(False)
    Next
End Sub

Sub Delay (DurationMs As Int)
    Dim target As Long = DateTime.Now + DurationMs
     Do While DateTime.Now < target
     Loop
End Sub

Sub getBits(v As Int,bitStart As Int,bitEnd As Int) As Int            'Not used
    Dim res As Int = 0
    For a = bitStart To bitEnd
        res = res + Power(2,a)    
    Next
    Return (Bit.ShiftRight(Bit.And(v,res),bitStart))
End Sub

A couple of the subs were not used but I didn't want to delete them (yet). The code gives a running light from left to right and back again.

Thanks to JoanRPM and Derez for their help (Question in Forum)
 
Top