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..."
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.
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.
-
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
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
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Ω.
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_
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);