B4R Tutorial Controllino Mega PLC Examples

Attached is a B4R project (using inline C) to manipulate the ports of the Controllino Mega. In this project we do the following:
1. Toggle the OVL (over voltage) LED of the PLC between on/off every second (Port E) via a timer
2. Toggle pins DO12 to DO19 (all on Port L) every second via the timer - split into 2 x groups of 4 DO's i.e DO 12, 13, 14, 15 switches ON/OFF immediately at the same time and DO 16, 17, 18, 19 switches OFF/ON immediately at the same time.

(2) above is useful if one wants to directly drive for eg a 24V DC motor in forward and reverse direction. It allows one to use for eg 2 (or more) x DO pins simultaneously to increase the available current to a DC motor. The pins need to be from the same PORT. See this posting about port manipulation (https://www.controllino.com/port-manipulation/)

20240330_131536.jpg


20240330_131547.jpg


Sample Code:

Port Manipulation:
Sub Process_Globals
    Public Serial1 As Serial
   
    Dim t As Timer
   
    Dim cnt As Int
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    cnt = 0
    t.Initialize("t_tick", 1000)
    RunNative("initDDRL", 0xff)
    RunNative("initDDRE", 0x80)
   
    t.Enabled = True
   
End Sub

Sub t_tick

    If cnt Mod 2 = 0 Then
        RunNative("ClearPortL", 0x00)
        RunNative("SetPortL", 0x0f)
        RunNative("SetPortE", 0x80)
    Else
        RunNative("ClearPortL", 0x00)
        RunNative("SetPortL", 0xf0)
        RunNative("ClearPortE", 0x7f)
    End If
   
    cnt = cnt + 1
End Sub

#if C
#define clear_port_bit(reg, bitmask) *reg &= ~bitmask
#define set_port_bit(reg, bitmask) *reg |= bitmask
#define pulse_high(reg, bitmask) clear_port_bit(reg, bitmask); set_port_bit(reg, bitmask);
#define pulse_low(reg, bitmask) set_port_bit(reg, bitmask); clear_port_bit(reg, bitmask);
#define clear_port(port, data) port &= data
#define set_port(port, data) port |= data

void initDDRA (B4R::Object* o) {
     DDRA |= o->toULong();
}

void initDDRB (B4R::Object* o) {
     DDRB |= o->toULong();
}

void initDDRC (B4R::Object* o) {
     DDRC |= o->toULong();
}

void initDDRD (B4R::Object* o) {
     DDRD |= o->toULong();
}

void initDDRE (B4R::Object* o) {
     DDRE |= o->toULong();
}

void initDDRF (B4R::Object* o) {
     DDRF |= o->toULong();
}

void initDDRG (B4R::Object* o) {
     DDRG |= o->toULong();
}

void initDDRH (B4R::Object* o) {
     DDRH |= o->toULong();
}

void initDDRJ (B4R::Object* o) {
     DDRJ |= o->toULong();
}

void initDDRK (B4R::Object* o) {
     DDRK |= o->toULong();
}

void initDDRL (B4R::Object* o) {
     DDRL |= o->toULong();
}

void ClearPortA (B4R::Object* o) {
  clear_port(PORTA, o->toULong());
}
void SetPortA (B4R::Object* o) {
  set_port(PORTA, o->toULong());
}

void ClearPortB (B4R::Object* o) {
  clear_port(PORTB, o->toULong());
}
void SetPortB (B4R::Object* o) {
  set_port(PORTB, o->toULong());
}

void ClearPortC (B4R::Object* o) {
  clear_port(PORTC, o->toULong());
}
void SetPortC (B4R::Object* o) {
  set_port(PORTC, o->toULong());
}

void ClearPortD (B4R::Object* o) {
  clear_port(PORTD, o->toULong());
}
void SetPortD (B4R::Object* o) {
  set_port(PORTD, o->toULong());
}

void ClearPortE (B4R::Object* o) {
  clear_port(PORTE, o->toULong());
}
void SetPortE (B4R::Object* o) {
  set_port(PORTE, o->toULong());
}

void ClearPortF (B4R::Object* o) {
  clear_port(PORTF, o->toULong());
}
void SetPortF (B4R::Object* o) {
  set_port(PORTF, o->toULong());
}

void ClearPortG (B4R::Object* o) {
  clear_port(PORTG, o->toULong());
}
void SetPortG (B4R::Object* o) {
  set_port(PORTG, o->toULong());
}

void ClearPortH (B4R::Object* o) {
  clear_port(PORTH, o->toULong());
}
void SetPortH (B4R::Object* o) {
  set_port(PORTH, o->toULong());
}

void ClearPortJ (B4R::Object* o) {
  clear_port(PORTJ, o->toULong());
}
void SetPortJ (B4R::Object* o) {
  set_port(PORTJ, o->toULong());
}

void ClearPortK (B4R::Object* o) {
  clear_port(PORTK, o->toULong());
}
void SetPortK (B4R::Object* o) {
  set_port(PORTK, o->toULong());
}

void ClearPortL (B4R::Object* o) {
  clear_port(PORTL, o->toULong());
}
void SetPortL (B4R::Object* o) {
  set_port(PORTL, o->toULong());
}

#end if

Port Groups:
MEGA:
1st group: D0, D1, D3
2nd group: D2
3rd group: D4, D5, D6, D7
4th group: D8, D9, D10, D11
5th group: D12, D13, D14, D15, D16, D17, D18, D19
6th group: D20, D21, D22
7th group: D23
 

Attachments

  • ControllinoPorts.zip
    1.2 KB · Views: 32

Johan Schoeman

Expert
Licensed User
Longtime User
A B4R project using the onboard RTC of the Controllino Mega. Library and sample project attached.

Sample code to set and read the date/time and to also set an alarm.

Sample Code:
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 300
#End Region
'Ctrl+Click to open the C code folder: ide://run?File=%WINDIR%\System32\explorer.exe&Args=%PROJECT%\Objects\Src

Sub Process_Globals
    
    Public Serial1 As Serial
    Dim aDay , aWeekDay, aMonth, aYear, aHour, aMinute, aSecond As Byte

    Dim t As Timer
    
    Dim p As Pin                  'will be using it for cont_rtc.CONTROLLINO_D0
    
    Dim p2 As Pin                 'RTC Alarm Interrupt (cont_rtc.CONTROLLINO_RTC_INTERRUPT)
    
    Dim p3 As Pin
    
    Dim cont_rtc As CONTROLLINO   'Get an instance of the CONTROLLINO library
    

End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    
    
    
    cont_rtc.Init                  'initialize the RTC
    
    p2.AddListener("RTCInterrupt_StateChanged")
    
    cont_rtc.ClearRTCAlarm         'clear all RTC alarms
    
    t.Initialize("t_tick", 1000)   'timer runs every 1 second
    
    p.Initialize(cont_rtc.CONTROLLINO_D0, p.MODE_OUTPUT)    'it will just blink the D0 LED in the timer
    
    p3.Initialize(cont_rtc.CONTROLLINO_D16, p3.MODE_OUTPUT)
    
    aDay = 25
    aWeekDay = 1
    aMonth = 2
    aYear = 24
    aHour = 18
    aMinute = 26
    aSecond = 0
    
    'Method 1 to set date and time
    'cont_rtc.SetTimeDate(aDay, aWeekDay, aMonth, aYear, aHour, aMinute, aSecond)

    'Method 2 to set date and time
    Dim datum() As Byte = "Mar 29 2024"
    Dim tyd() As Byte = "14:58:45"
    Dim err As Byte = cont_rtc.SetTimeDateStrings(datum, tyd)
    Log("err = ", err)
    
    p2.Initialize(cont_rtc.CONTROLLINO_RTC_INTERRUPT, p2.MODE_INPUT_PULLUP)    'pull the CONTROLLINO_RTC_INTERRUPT pin HIGH (see the hover help - it is pin 73)
    Dim alarmset As Byte = cont_rtc.SetRTCAlarm(14, 59)    'set the time that the alarm should be triggered (RTC time - it is not relative to current RTC time but actual time)
    If alarmset = 0 Then
        p3.DigitalWrite(True)                             'if the alarm has been set then light up the LED of pin CONTROLLINO_D16
    End If
    t.Enabled = True                     'enable the timer
    
End Sub

Sub t_tick
    
    p.DigitalWrite(Not(p.DigitalRead))    'blink the LED of D0
    
    cont_rtc.PrintTimeAndDate             'prints the date and time to the log (eg 29/3/24   11:14:28)
    
    aDay = cont_rtc.GetDay                'get the Day of the month
    aWeekDay = cont_rtc.GetWeekDay        'get the weekday of the date (0 = Sun, 6 = Sat)
    aMonth = cont_rtc.GetMonth            'get the month (1 to 12)
    aYear = cont_rtc.GetYear              'get the year (it returns the last 2 digits eg 24 for 2024)
    aHour = cont_rtc.GetHour              'get the hour (1 to 12 or 0 to 23)
    aMinute = cont_rtc.GetMinute          'get the minutes (0 to 59)
    aSecond = cont_rtc.GetSecond          'get the seconds (0 to 59)
    
    Log("aDay = " , aDay)                 'log what was read from the RTC
    Log("aWeekday = " , aWeekDay)
    Log("aMonth = " , aMonth)
    Log("aYear = " , aYear)
    Log("aHour = " , aHour)
    Log("aMinute = " , aMinute)
    Log("aSecond = " , aSecond)
    Log(" ")
    
    If p2.DigitalRead = False Then       'P2 was pulled HIGH when initialized - Once the alarm trigger is will be pulled LOW
        cont_rtc.ClearRTCAlarm           'Clear the alarm after it was triggered
        Log("Alarm triggered!")          'Log Alaram Triggered
        p3.DigitalWrite(False)           'switch off the LED of pin CONTROLLINO_D16 when the alarm was triggered
        
        If aMinute < 59 Then
            t.Enabled = False
            Delay(200)
            cont_rtc.SetRTCAlarm(aHour, aMinute + 1)
            t.Enabled = True
            p3.DigitalWrite(True)               'switch on the LED of CONTROLLINO_D16
        Else if aMinute = 59 Then
            t.Enabled = False
            Delay(200)
            cont_rtc.SetRTCAlarm(aHour + 1 , 0)    'switch on the LED of CONTROLLINO_D16
            t.Enabled = True
            p3.DigitalWrite(True)
        End If
        
    End If

    
End Sub

Sub RTCInterrupt_StateChanged (State As Boolean)
    Log("!!!!!!!!!!!!!")
    Log("GOTCHA")
    Log("!!!!!!!!!!!!!")
    Log(" ")
    
End Sub
 

Attachments

  • rControllino.zip
    105.3 KB · Views: 26
  • ControllinoNew.zip
    2.2 KB · Views: 22

Johan Schoeman

Expert
Licensed User
Longtime User
Connected a HC-05 Bluetooth module to the header pins of the Controllino Mega and can control the Mega from an old B4A app that I have done to control my DSTV decoder via Bluetooth and IR.

B4R code:
#Region Project Attributes
    #AutoFlushLogs: True
    #CheckArrayBounds: True
    #StackBufferSize: 300
#End Region

Sub Process_Globals
    Public Serial1 As Serial
    Private SoftwareSerial1 As SoftwareSerial
    Private astream As AsyncStreams
    Dim cont As CONTROLLINO
    
    Dim r0 As Pin

End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Log("AppStart")
    r0.Initialize(cont.CONTROLLINO_R0, r0.MODE_OUTPUT)
    
    SoftwareSerial1.Initialize(9600, cont.CONTROLLINO_D9, cont.CONTROLLINO_D10) 'software serial port on pins 10 and 11
    astream.Initialize(SoftwareSerial1.Stream, "astream_NewData", Null)
End Sub

Sub AStream_NewData (Buffer() As Byte)
    
    For i = 0 To Buffer.Length - 2 Step 2
        If Buffer(i + 1) = 1 Then

            r0.DigitalWrite(True)
            
            Dim b() As Byte = "R0 is now ON"
            Dim c() As Byte = CRLF
            astream.Write(b)
            astream.Write(c)
            
            
        else If Buffer(i + 1) = 2 Then

            r0.DigitalWrite(False)
            
                        
            Dim b() As Byte = "R0 is now OFF"
            Dim c() As Byte = CRLF
            astream.Write(b)
            astream.Write(c)

        End If       
    Next
    
End Sub

20240407_154217.jpg
 
Top