Autres articles / Other articles

Understanding ARDUINO card connectors

published: 4 November 2019 / updated 18 June 2020

Lire cette page en français

 

Preamble

Unlike the C language for ARDUINO, the FORTH language does not have an IDE integrating the translation of the connector numbers to the pin numbers.

In C language:

void setup()
{
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(11, OUTPUT);
    pinMode(13, OUTPUT);
    pinMode(A2, OUTPUT);
    pinMode(A3, OUTPUT);
    pinMode(A4, OUTPUT);
}

The numbers of the pins correspond to the numbers inscribed on the card in front of each connector:

connector organization for ARDUINO UNO

In C language, this translation is done through a complex C library. This library associates the connector number to its PORT register and the corresponding bit in this port.

These C language libraries simplify programming for beginners. In return, the code binary generated by the compiler C is cluttered with slags specific to these libraries.

FORTH language does not use any libraries outside of an initial dictionary. It will therefore be necessary define for each connector the PORT and the bit associated with a pin as defined in language C.

This definition is initially a constraint. But if we then master the analysis of card connectors ARDUNIO, it becomes very easy to create the words managing the PORTS and registers.

Analysis of ARDUINO board connectors

Here is the map of the connectors of an ARDUINO UNO board:

connector organization for ARDUINO UNO

Isolate the part of the connectors managing the PORT B:

extract from the connector organization for ARDUINO UNO

From left to right for the connector 8:

  8 -> 14 -> PB0 -> 8 -> CLK0 -> PCINT0 -> ICP1

Detailed analysis of this line:

In all this information, the one that interests us in priority is the association between the physical connector (here 8) and the PORT, here PB0: Port B bit 0

FORTH translation of a physical connector

In FORTH, we define the ports as constants:

\ PORTB 
37 constant PORTB	\ Port B Data Register 
36 constant DDRB	\ Port B Data Direction Register 
35 constant PINB	\ Port B Input Pins 

These addresses for the PORTB are identical regardless of the ARDUINO cards.

On an ARDUINO board, a port is an 8-bit register accessible by its address, here 37 in decimal, $25 in hexadecimal:

37 constant PORTB	\ Port B Data Register 

is equivalent as:

$25 constant PORTB	\ Port B Data Register 

To isolate a bit in this register, here PORTB, it is necessary to use a binary mask:

So, a connector will always be accessible via a pair of values:

You can define a pin as follows, for example for connector 8:

: pin8 ( --- msk adr )
    %00000001 PORTB ;

To activate this connector, it will be necessary to declare in the DDRB register that this connector is activated at the output:

: init.out.pin8 ( ---) 
    pin8 1- mset ; 

Then to enable and disable this connector 8:

: pin8.on ( ---) 
    pin8 mset ; 
: pin8.off ( ---) 
    pin8 mclr ; 

Here we have done at the simplest, to illustrate the management of connector 8. We will see later how to factor the code.

Naming the connectors

Let's go back to our connector 8 which corresponds to the first bit in PORT B. What does it plug into? An LED? A relay? A buzzer? So why name pin8?

If we develop an application on our ARDUINO card, it may happen that we are obliged to move the LED, the relay, the buzzer to another connector. And so, it will be necessary to redefine PIN8

: pin8 ( --- msk adr ) 
    %10000000 PORTF ; 

Here, we moved the connector to the highest weight bit of PORT F on an ARDUINO MICRO board (Connector 42). Without renaming pin8, the program will work.

The logic would be to rename pin8 to pin42. But if we have used pin8 later in our source code, we will need rename all these occurrences of pin8.

The solution is to rename according to the use of the connector. We use the connector 8 to light a red LED? So we define a word LED.red like this:

: LED.red ( --- msk adr ) 
    %00000001 PORTB ; 
: init.LED.red ( ---) 
    LED.red 1- mset ; 
: LED.red.on ( ---) 
    LED.red mset ; 
: LED.red.off ( ---) 
    LED.red mclr ; 

You understand immediately that moving the red LED on another connector, it just change the definition of the word LED.red. All the others definitions using LED.red will not need to be changed.

This is the naming scheme that is used in this article Revisited management of traffic lights

Extract:

: traffic.lights ( ---) 
    LED.green   led.ON   3000 ms    LED.green   led.OFF 
    LED.yellow  led.ON    800 ms    LED.yellow  led.OFF 
    LED.red     led.ON   3000 ms    LED.red     led.OFF  ; 

Without reading the beginning of the code, you immediately understand how works the word traffic.lights!

Factoring the FORTH code

When programming in FORTH language, you should try to write definitions as well. simple and shorter as possible. If the same code is repeated in several definitions, it is necessary to group these portions of code into a new word and replace these portions of code by that word.

This technique is called code factorization. FORTH language is not a object-oriented language. It's even a language closer to the assembler than any other programming language. It's easy to make mistakes and difficult to find and delete them.

By creating words with simple definitions, the focus of these words becomes easy. Every word, once tested, must become a black box, a box tested and reliable. Only must be taken into account the nature of the input and output data for each word.

Let's go back to our LEDs on connectors 8 and following of PORT B. Connect four LEDs and a relay:

: LED1 ( --- msk adr ) 
    %00000001 PORTB ; 
: LED2 ( --- msk adr ) 
    %00000010 PORTB ; 
: LED3 ( --- msk adr ) 
    %00000100 PORTB ; 
: LED4 ( --- msk adr ) 
    %00001000 PORTB ; 
: RELAY ( --- msk adr ) 
    %00010000 PORTB ; 

In the FORTH language, the word : is a word definition word, such as variable or constant. Although being a close language of the machine, the FORTH language has two words, CREATE DOES> to create word definitions words.

: defPIN: ( PORTx mask ---  |  --- mask port) 
    create 
        c, c,           \ compile PORT and pin mask 
    does> 
        dup c@          \ push pin mask 
        swap 1+ c@      \ push PORT 
  ; 

We just defined the word defPIN: which is a word to define the connectors:

eeprom 
%00000001 PORTB defPIN: LED1 
%00000010 PORTB defPIN: LED2 
%00000100 PORTB defPIN: LED3 
%00001000 PORTB defPIN: LED4 
%00010000 PORTB defPIN: LED5 

In the word defPIN:, the code part create , , recovers stacked data when defPIN: is executed.

In the word defPIN:, the code part does> dup @ swap 2+ @ retrieves the memory address to which the previously compiled parameters are stored and stack this data. If we run LED1, we will stack the values 1 and PORTB.

FORTH language is extensible. When you develop a program, there is no one side the language and on the other your program.

An application in FORTH language extends the FORTH language. Your application integrates language FORTH just like all the pre-defined words of the FORTH language.

The vast majority of versions of the FORTH language are written at 20% in assembler and at 80% in FORTH language!

FORTH contains all the tools to create a meta-language!

Previously, we had defined:

: LED.red ( --- msk adr ) 
    %00000001 PORTB ; 
: init.LED.red ( ---) 
    LED.red 1- mset ; 
: LED.red.on ( ---) 
    LED.red mset ; 
: LED.red.off ( ---) 
    LED.red mclr ; 

Here is the factored code:

\ Set DDRx so its corresponding pin is output. 
: output ( pinmask portadr -- ) 
    1- high 
  ; 
\ Set DDRx so its corresponding pin is input. 
: input  ( pinmask portadr -- )    
    1- low 
  ; 
\ Turn a pin on, dont change others 
: high ( pinmask portadr -- ) 
    mset 
  ; 
\ Turn a pin off, dont change others 
: low ( pinmask portadr -- ) 
    mclr 
  ; 

Utilisation:

LED.red output 
LED.red high 

Turn on the red LED ...

PORT B on ARDUINO cards

On an ARDUINO UNO board, only bits 0 to 5 of PORT B are physically accessible on the map ARDUINO. On the ARDUINO MEGA board all the bits of PORT B are accessible.

In this table, you will find the correspondence of the bits of PORT B and the physical connectors Related:

ARDUINO B7B6B5B4B3B2B1B0
UNO 1312111098
MEGA 13121110 50515253
MICRO 12302928111098
NANO 171615141312

If you have to change an ARDUINO card by another one of a model, it will take take into account these disparities to adapt your code in FORTH language.

If you correctly factor your code in FORTH language, it will be easy to isolate the initialization part specific to your ARDUINO card type.

Caution: do not confuse physical connector numbers and pin numbers

On the ARDUINO cards, the physical connectors are marked, some by numbers, others by their function, example: GND, TX, RX, 5V, etc ...

The mapping for associating pin numbers with physical connectors is in this document:
 Pin out map on ARDUINO DUE
 Pin out map on ARDUINO MEGA 2560
 Pin out map on ARDUINO MICRO
 Pin out map on ARDUINO NANO
 Pin out map on ARDUINO UNO
 Pin out map on ARDUINO YUN

For example, the led '13' which is connected to the ARDUINO MEGA board with the physical terminal 13 is related to the PIN 26. In all our texts, the term "pin" will always refer to PIN code XX as referenced in the technical documents of ARDUINO cards. The mention of a physical connector will be done with the term 'terminal'. Example:

  PIN 19 (terminal 53) (penultimate terminal, all at the bottom, left on an ARDUINO MEGA 2560 board)

To learn more about how to program the connectors of the different ARDUINO boards:
Understanding ARDUINO card connectors