General Note GCC 

The latest version of Pi OS only supplies GCC 8.3 in a bare metal compiler configuration arm-none-eabi and this is the Kit you should select.

The alternative 10.2 targets Linux and cannot be used to compile Pico programs.

Windows 10 currently supplies 10.3 arm-none-eabi for bare metal targets.

General Note RDP

The latest version of Pi OS needs some tweeking to make Windows remote desktop work.

See the article on I Programmer - Remote Desktop To A Headless Pi Running Bullseye

 

Page 25:

the instruction should read:   "git submodule update --init"  (minus minus init, instead of minus init minus: "-init-")

Page 27

before moving on :

becomes

before moving on by clicking on the "four little square" icon in the column at the left of the screen, as shown on the picture below. 

Page 30:

file isn't detected, then from the View top menu, select the Command Palette..."

Change:

If this doesn’t work and the CMakeLists.txt file isn’t detected then use the command Palette to issue the command CMake Quick Start, but don’t overwrite the CMakeLists.txt file you already have.

to

If this doesn’t work and the CMakeLists.txt file isn’t detected then use the command Palette, (View, Command Palette), to issue the command CMake Quick Start, but don’t overwrite the CMakeLists.txt file you already have.

change

There are many ways to start a build of the project, but all of the commands are available if you select the CMake extension and then click on the three dots menu.

to

There are many ways to start a build of the project, but all of the commands are available if you select the CMake extension (by clicking on the icon at the left of the screen, the rectangle with a triangle in it) and then click on the three dots menu.

if you select the CMake extension (by clicking on the icon at the left of the screen, the rectangle with a triangle in it) and then click on the dots at the top of the column that is to the right of the icons column"
 
Page 36
the table:

PicoProbe

Pi Pico

GND

SWD GND

GP2

SWDIO

GP3

SWCLK

should read:

PicoProbe

Pi Pico

GND

SWD GND

GP3

SWDIO

GP2

SWCLK

i.e. swap GP2 and GP3

Also add for clarity:

Note: this does not connect the serial port which is useful in printf debugging among other things. See Chapter 6.

Page 41

 7th bullet should read: "UF2" instead of "UF4".

 

Page 46

Change

This uses the same CmakeLists.txt file as blinky in the previous chapter and the same launch.json file. The only difference is that now we are using GP22.

to

This uses the same CMakeLists.txt file as blinky in the previous chapter and the same launch.json file. The only difference is that now we are using GP22.

 i.e. change m to M

 

Page 54:

change

You can see that this is that case by swapping the order of the instructions:

to

You can see that this is the case by swapping the order of the instructions:

Page 54:

Change

Both wait for the specified time in microseconds but the sleep_us saves power and the busy_wait doesn’t but is more more accurate.

to

Both wait for the specified time in microseconds but the sleep_us saves power and the busy_wait doesn’t but is more accurate.

Page 61

As the internal pull-down resistor is used, the switch can be connected to the line and ground without any external resistors:

should read:

As the internal pull-up resistor is used, the switch can be connected to the line and ground without any external resistors:

Page 64:

Change

An LED is a non-linear electronic component – the voltage across is stays more or less the same irrespective of the current passing through the device.

to

An LED is a non-linear electronic component – the voltage across it stays more or less the same irrespective of the current passing through the device.

Page 67:

 

Change

From its datasheet you can discover that the max collector current is 800mA and beta is at least 50, which makes it suitable for driving a 20mA LED with a GPIO current of at most 20/50mA = 0.4mA. 

to

From its datasheet you can discover that the max collector current is 800mA and beta is at least 50, which makes it suitable for driving a 20mA LED with a GPIO current of at most 20mA/50 = 0.4mA, where 50 is the HFE or beta.

 

Page 68:

change

To limit the current to 0.4mA would need a resistor of 2.7/0.4kΩ. = 6.7kΩ.

to

To limit the current to 0.4mA would need a resistor of 2.7V/0.4mA = 6.7kΩ.

change 

Assuming a forward voltage drop of 1.6V and a current of 20mA the resistor is given by (3.3-1.6)/20kΩ = 85Ω. In practice, we could use anything in the range 82Ω to 100Ω.

to

Assuming a forward voltage drop of 1.6V and a current of 20mA the resistor is given by (3.3-1.6)V/20mA = 85Ω.

Page 76:

change

Vout = V R2/(R1+R2)

to

Vout = V * R2/(R1+R2)

Page 81:

change

As the internal pull-down resistor is used, the switch can be connected to the line and ground without any external resistors:

to

As the internal pull-upresistor is used, the switch can be connected to the line and ground without any external resistors:

 

Page 98:

Change

Notice that an event, or an event queue, cannot increase the program’s throughput or its latency – the time to react to an input.

to

Notice that an event, or an event queue, cannot increase the program’s throughput or decrease its latency – the time to react to an input.

Page 113:

change

Of course, even though the PWM line can generate pulses very fast pulses, usually what you want to do is change the nature of the pulses and this is a slower process involving the processor.

to

Of course, even though the PWM line can generate very fast pulses, usually what you want to do is change the nature of the pulses and this is a slower process involving the processor.

Page 115:

Change

To make use of the PWM hardware you need to change the libraries statement in CMakeLists.txt to:

target_link_libraries(myprogram  pico_stdlib
                               hardware_gpio hardware_pwm)

To make use of the PWM hardware you need to change the libraries statement in CMakeLists.txt to:

target_link_libraries(myprogram  pico_stdlib
                               hardware_gpio hardware_pwm)

that is you you need to add hardware_pwm to the libraries.

 

to

To make use of the PWM hardware you need to change the libraries statement in CMakeLists.txt to:

target_link_libraries(myprogram  pico_stdlib
                               hardware_gpio hardware_pwm)

that is you need to add hardware_pwm to the libraries.

 

 

Page 131

The line in the first new paragraph:

The PWM output in this configuration mimics the workings of an 8-bit A-to-D converter.

shoudl read:

The PWM output in this configuration mimics the workings of an 8-bit D-to-A converter.

i.e. swap A and D.

 

Page 135

The graph axis labels need to be switched.

Page 155:

Function "void BiMotorspeed()" - At the top of the page, are you sure "m->forward = true" must be "= true" in the two cases of the "if" statement ? Shouldn't the second be "false" ?

Page 167

So for example, if we use GP28 as the first GPIO line the four lines are GP18, GP19, GP20 and GP21 and the first element of stepTable sets just GP21 to high.

should read

So for example, if we use GP18 as the first GPIO line the four lines are GP18, GP19, GP20 and GP21 and the first element of stepTable sets just GP21 to high.

i.e. change GP28 to GP18

Page 171

the rotation is in rotations per second not per minute - I forgot to multiply by 60.

It should read:

In this case, H‑bridge GP21 is A, GP20 is B, GP19 is A- and GP18 is B-. The stepping speed is such that a 200-step motor, i.e. 400 half steps, will rotate in 400*1 ms= 0.4 s, i.e. 2.5 rps (revolutions per second), which is a good starting speed. Decrease the sleep time for a higher speed. 

The error is also on:page 173

Page 172:

change

The second cancels a timer.

to

The third cancels a timer.

Page 173

Notice that we have to deal with the case of speed set to zero separately to avoid a divide by zero exception. The speed is specified in rps *100. So setting speed to 250 gives a rotation of 2.5rps.

Page 182:

There are 3 references to MSIO on the page they should be changed MISO 

Page 187

Next we can send some data and receive it right back:

uint8_t read_data = bcm2835_spi_transfer(0xAA);

 remove the program line and change the : to ;

Next we can send some data and receive it right back.

Page 188:

Change  MSIO  to MISO

Page 188 

If you connect a logic analyzer to the three pins involved – 4, 6 and 7, you will see the data transfer:

 change to:

If you connect a logic analyzer to the three GPIO lines involved – 4, 6 and 7, you will see the data transfer:

 i.e change pins to GPIO lines

 

 

Page 216:

change ic21 to  i2c1

 

 

Page 229

Temperature in °C= -46.85 + 175.72 * data16 / 216

change to

Temperature in °C= -46.85 + 175.72 * data16 / 216 

change 216 to 216

Page 230

RH= -6 + 125 * data16 / 216

change to 

RH= -6 + 125 * data16 / 216

change 216 to 216

Page 241:

change

The complete program is but remember that it needs the PIO program and the CMakeLists.txt file:

to

The complete program is listed below, but remember that it needs the PIO program and the CMakeLists.txt file:

Page 243

You can use the registers to implement a for loop with up to 32 repeats. The jmp instruction can test the value of a register for zero and auto-decrement it after the test. This means an n repeat for loop can be constructed as:

set x,n
loop: nop
jump x--, loop

Using this you can slow the rate at which the GPIO line is toggled by repeating the nop 32 times. However, even if you use:

set x,n
loop: nop [31]
jump x--, loop

the effective rate of toggling the GPIO line is still too great to see an LED flash. To slow it down even more you need two nested loops.

 

change to

 

You can use the registers to implement a for loop with up to 32 repeats. The jmp instruction can test the value of a register for zero and auto-decrement it after the test. This means an n repeat for loop can be constructed as:

set x,n
loop: nop
jmp x--, loop

Using this you can slow the rate at which the GPIO line is toggled by repeating the nop 32 times. However, even if you use:

set x,n
loop: nop [31]
jmp x--, loop

the effective rate of toggling the GPIO line is still too great to see an LED flash. To slow it down even more you need two nested loops.

i.e. change jump to jmp

Page 247

This seems simple, but the set pindir is more complicated than you might expect. The set instruction sets the direction of the SET group of pins. The literal value used in the instruction is used as a mask to set the pin directions. This means that it can only set the direction of the first five GPIO lines in the SET group. This usually isn’t a problem as using more than five GPIO lines for output is uncommon. However, the out instruction sends the data from the OSR to the first two GPIO lines in the OUT group, not the SET group. You can see that the set instruction only enables the first two lines of the OUT group if they are the same in both groups.

change to 

This seems simple, but the set pindirs is more complicated than you might expect. The set instruction sets the direction of the SET group of pins. The literal value used in the instruction is used as a mask to set the pin directions. This means that it can only set the direction of the first five GPIO lines in the SET group. This usually isn’t a problem as using more than five GPIO lines for output is uncommon. However, the out instruction sends the data from the OSR to the first two GPIO lines in the OUT group, not the SET group. You can see that the set instruction only enables the first two lines of the OUT group if they are the same in both groups.

i.e. pindir -> pindirs

Page 253

sm_config_set_sideset_pins(&c,2);
pio_gpio_init(pio0, 2);
pio_gpio_init(pio0, 3);

The first instruction has to be changed to:

pio_sm_set_consecutive_pindirs(pio0,sm,2,2,true);

 

Page 300

change 

The complete program to read and display the temperature is:
#include
#include "pico/stdlib.h"
#include "hardware/gpio.h"
int presence(uint8_t pin)
{
gpio_set_dir(2, GPIO_OUT);
gpio_put(pin, 1);
sleep_ms(1);
gpio_put(pin, 0);
sleep_us(480);
gpio_set_dir(pin, GPIO_IN);
sleep_us(70);
int b = gpio_get(pin);
sleep_us(410);
return b;
}

To

The complete program to read and display the temperature is:
#include 
#include "pico/stdlib.h"
#include "hardware/gpio.h"
int presence(uint8_t pin)
{
gpio_set_dir(pin, GPIO_OUT);
gpio_put(pin, 1);
sleep_ms(1);
gpio_put(pin, 0);
sleep_us(480);
gpio_set_dir(pin, GPIO_IN);
sleep_us(70);
int b = gpio_get(pin);
sleep_us(410);
return b;
}

i.e. change 2 to pin in first line of function.

 

Page 336

int getBlocks(uint8_t buf[], int len, int num, char target[])
{
for (int i = 0; i < num; i++)
{ if (uart_is_readable_within_us(uart1, 1000 * 1000));
getBlock(buf, len);
if (strstr(buf, target))
return i;
}
return -1;
}

change to:

int getBlocks(uint8_t buf[], int len, int num, char target[])
{
for (int i = 0; i < num; i++)
{ if (uart_is_readable_within_us(uart1, 1000 * 1000))
{
getBlock(buf, len);
if (strstr(buf, target))
return i;
}
}
return -1;
}

i.e. add {} around if  body.

Page 330 and 345:

change

uart_set_translate_crlf(uart0,true);

to

uart_set_translate_crlf(uart1,true);

 

 
 
 
 
 
Page 345: Idem to page 330 above.

General Note GCC 

The latest version of Pi OS only supplies GCC 8.3 in a bare metal compiler configuration arm-none-eabi and this is the Kit you should select.

The alternative 10.2 targets Linux and cannot be used to compile Pico programs.

Windows 10 currently supplies 10.3 arm-none-eabi for bare metal targets.

General Note RDP

The latest version of Pi OS needs some tweeking to make Windows remote desktop work.

See the article on I Programmer - Remote Desktop To A Headless Pi Running Bullseye

General Note PIO

To avoid having to use GPIO lines in SPI mode the driver makes use of one of the PIOs. This means that you should avoid using the same PIO as the WiFi driver for general purpose I/O. Which PIO is used is set by

#define CYW43_SPI_PIO_PREFERRED_PIO 1

You can override this if you want to but it is simpler to use PIO 0 for your own PIO programs. The driver uses a single state machine and ten bytes of instruction memory. If you want to use PIO 1 you can use pio_claim_unused_sm to find a free state machine.

All of the examples in the PIO chapter use PIO 0.

General Note Windows Installer

As of SDK 1.5 there is an official installation script for Windows and it makes the job of getting started much simpler. You can find it at:

https://github.com/raspberrypi/pico-setup-windows

and it is easy to use and it works.

To find the exe file you first need to navigate to the latest releases:

Then download the appropriate installer from the Assets section.

And run the .exe file from the command prompt.

At the time of writing it automatically installs and configures the following:

  1. Arm GNU Toolchain

  2. CMake

  3. Ninja

  4. Python 3.9

  5. Git for Windows

  6. Visual Studio Code

  7. OpenOCD

The installation provides a specially configured version of VS Code – Pico-Visual Studio Code and a Pico configured PowerShell and Command Prompt. In fact the PowerShell is used to start VS Code with the correct environment parameters. It also installs Ninja as the make utility not the default Nmake.

You need to always ensure that you start VS Code using the Pico shortcut otherwise you will get an unconfigured VS Code that will not know how to compile your program.

Errata

Page 71

Swap the Emitter Collector labels on the diagram at the top of the page. The Emitter is always the one with the arrow!

Page 84 Top line

Change:

We have already met the functions that sets a GPIO line to input or output:

To read:

We have already met the functions that set a GPIO line to input or output:

Page 85

Change:

One of the most common input circuits is the switch or button. If you want another external button you can use any GPIO line and the circuit explained in the previous chapter. That is, the switch has to have either a pull-up or pull-down resistor either provided by you or a built-in one enabled using software.

To read:

One of the most common input circuits is the switch or button. If you want add a button you can use any GPIO line and the circuit explained in the previous chapter. That is, the switch has to have either a pull-up or pull-down resistor either provided by you or a built-in one enabled using software.

Change:

The program simply tests for the line to be pulled low by the switch being closed and then sets GP21 high. If you connect GP21 to an LED or a logic analyzer you will see the effect of the button being closed – the LED will light up while it is pressed. Notice GP22 goes low to indicate that the switch is pressed.

To read

The program simply tests for the line, GP21, to be pulled low by the switch being closed and then sets GP22 high. If you connect GP22 to an LED or a logic analyzer you will see the effect of the button being closed – the LED will light up while it is pressed.

 Page 88

If you are only interested in transmitting data from the Pico you only need to connect Pin 1 and Pin10.

change to 

If you are only interested in transmitting data from the Pico you only need to connect Pin 1 and Pin 2.

 Page 157 spotted by Gordon Macdonald

 

Change true (highlighted in red) to false.

void BiMotorspeed(BiMotor *m, int s, bool forward)
{
    if (forward)
{
pwm_set_duty(m->slice, m->Bchan, 0);
pwm_set_duty(m->slice, m->Fchan, s);
m->forward = true;
}
else
{
pwm_set_duty(m->slice, m->Fchan, 0);
pwm_set_duty(m->slice, m->Bchan, s);
m->forward = true;
} m->speed = s;
}

Page 287

The fist line of int presence(uint8_t pin) 

gpio_set_dir(2, GPIO_OUT);

should be

gpio_set_dir(pin, GPIO_OUT);

The function is correct in the final listing.

Spotted by Larry Simoneau - many thanks.

Page 344

Change the body function from:

err_t body(void *arg, struct altcp_pcb *conn,
                                      struct pbuf *p, err_t err)
{
    printf("body\n");
    pbuf_copy_partial(p, myBuff, p->tot_len, 0);  
    printf("%s", myBuff);
    return ERR_OK;
}

to

err_t body(void *arg, struct altcp_pcb *conn,
                                      struct pbuf *p, err_t err)
{
    printf("body\n");
    pbuf_copy_partial(p, myBuff, p->tot_len, 0);
    pbuf_free(p);
    printf("%s", myBuff);
    return ERR_OK;
}
 
That is add pbuf_free(p). Without it there is a memory leak that slows the calls to the client down until at around 25
calls it no longer has enough memory to work.

Errata

Page 85 (Spotted by Federico Arismendi - thanks!) 

The line

['harry', 'ian', 'lucy', 'mike', 'sue']

should be 

['sue', 'ian', 'mike', 'lucy', 'harry']

A copy and paste error.

 

Errata

Page 92 (Spotted by Federico Arismendi - thanks!) 

The line

I = pinIn.value()

should be 

i = pinIn.value()

The text processor we use has a habit of automatically upper casing i to I  !

 

Errata

 Page  83

self.finished.set()  the final line is superfluous

Page 114

Change

myCond = Condition()

.to

Co = Condition()