Connexion au réseau local du Pïco W

Utiliser l'interface Wifi pour, dans un premier temps, se connecter à un réseau local impose d'appréhender la structure des librairies du SDK traitant du réseau.


On peut considérer que l'accès au réseau se fait via deux librairies : "pico_cyw43_arch" et "lwIP". Dans les faits la librairie "pico_cyw43_arch" encapsule les accès à la librairie "lwIP". "pico_cyw43_arch" fournie un cadre, permettant de se connecter à un réseau, de définir le mode de fonctionnement en Wifi, de contrôler la diode du Pico W, etc... "lwIP" (Qui est une librairie tierce) fournie les fonctionnalités de lecture/écriture en UDP, TCP/IP, etc...


La librairie "pico_cyw43_arch" est fournie en 3 versions :


 - pico_cyw43_arch_lwip_poll : Pour encapsuler, et donc utiliser les fonctions dites "RAW" de la librairie "lwIP" en mode interrogatif. Cette version impose de venir lire périodiquement l'état des fonctionnalités réseau et ne supporte pas le mode multitâche ou multiprocesseur.(Bref : Elle a peu d'adeptes !!!)

 - pico_cyw43_arch_lwip_threadsafe_background : Pour encapsuler, et donc utiliser les fonctions dites "RAW" de la librairie "lwIP" en mode interruptible et multitâche/multiprocesseurs. (Bref : C'est celle qui s"impose à la majorité d'entre nous).

 - pico_cyw43_arch_lwip_sys_freertos : Pour encapsuler, et donc utiliser toutes les fonctions de la librairie "lwIP" lorsque le Pico est configuré pour fonctionner sous FreeRTOS.

Donc, sauf si vous utilisez FreeRTOS, les fonctions de lecture/écriture réseau sont celles dites "RAW" de la librairie "lwIP". Elles sont documentées ici : lwIP Raw API. L'exemple Communications UDP utilise ces fonctions. La seule fonction de "lwIP" que nous utlisons dans l'exemple ci-dessous permet simplement de retourner l'adresse IP du Pico W sous forme lisible. Toutes les autres fonctions utlisées sont celles internes à "pico_cyw43_arch".


   Fichier lwipopts.h

Lorsque vous utilisez les fonctions de la librairie "lwIP", vous devez insérer dans votre répertoire prrojet un fichier nommé "lwipopts.h". Ce fichier n'est requis que pour le Pico W lorsqu'on utilise celui-ci pour des échanges réseau. Dans cet exemple, il n'est pas nécessaire. Dans la très grande majorité des cas il n'y a aucune modification à y apporter. Vous ne créez jamais ce fichier par vous même, le SDK vous le fourni (sous un autre nom !!!). Pour le copier dans votre répertoire projet, il suffit d'ouvrir un terminal et d'exécuter la commande de copie de fichier suivante qui copie le fichier "lwipopts_examples_common.h" situé dans le répertoire ""/pico/pico-examples/pico_w/wifi" vers le répertoire du projet en le rennomant en "lwipopts.h". Les caractères "???" de la ligne de commande doivent être remplacés par ceux de votre installation.


cp /home/???/pico/pico-examples/pico_w/wifi/lwipopts_examples_common.h /home/???/pico/pico-projects/test/lwipopts.h


Dans certains cas rares, il sera peut-être nécessaire de modifier ce fichier. Généralement par des modifications d'options.

Code source

Ci dessous les fichiers "CMakeLists.txt" et "wifi.cpp" d'un projet du même nom : "wifi" :

CMakeLists.txt

 - Note : Notez la présence de la ligne "set(PICO_BOARD pico_w)" cara ce projet ne peut fonctionner que sur un Pico W.

 - Note : Notez l'ajout de "pico_cyw43_arch_lwip_threadsafe_background dans la section "target_link_libraries".


cmake_minimum_required(VERSION 3.13)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
set(PICO_SDK_PATH "/home/alain/pico/pico-sdk")

set(PICO_BOARD pico_w)

# Pull in Raspberry Pi Pico SDK (must be before project)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)

if (PICO_SDK_VERSION_STRING VERSION_LESS "1.4.0")
message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.4.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
endif()

project(wifi C CXX ASM)

# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()

# Add executable. Default name is the project name, version 0.1
add_executable(wifi wifi.cpp )
pico_set_program_name(wifi "wifi")
pico_set_program_version(wifi "0.1")

pico_enable_stdio_uart(wifi 1)
pico_enable_stdio_usb(wifi 0)

pico_add_extra_outputs(wifi)

# Add the standard include files to the build
target_include_directories(wifi PRIVATE
${CMAKE_CURRENT_LIST_DIR}
${CMAKE_CURRENT_LIST_DIR}/.. # for our common lwipopts or any other standard includes, if required
)

# Add any user requested libraries
target_link_libraries(wifi
  pico_stdlib
  pico_cyw43_arch_lwip_threadsafe_background
)

wifi.cpp

Dans ce code, vous devrez remplacer les chaines "ssid" et "password" par le nom de votre réseau local et son mot de passe.


L'utilisation de la constante "CYW43_COUNTRY_WORLDWIDE" à la ligne "cyw43_arch_init_with_country" n'est pas standard. Il aurait fallu utiloiser la constante "CYW43_COUNTRY_FRANCE". J'ai cependant constaté que l'utilisation de cette dernière constante conduisait à des echecs sur certains réseaux wifi alors que la constante "CYW43_COUNTRY_WORLDWIDE" semble toujours donné un résultat de connection correcte.


// C regular includes
#include ‹stdio.h›

// Pico SDK includes
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"

// lwIP Includes
#include "lwip/ip_addr.h"
#include "lwipopts.h"

int main()
{
  stdio_init_all();

  printf("Connection au réseau WIFI. Attendez quelques secondes...\n");

  // Initialize the WIFI country
  if(cyw43_arch_init_with_country(CYW43_COUNTRY_WORLDWIDE))
  {
    printf("Erreur : Définition du pays\n");
    return 0;
  }

  // Enable the WIFI
  cyw43_arch_enable_sta_mode();

  // Connect to the WIFI SSID with a 10 seconds timeout
  if(cyw43_arch_wifi_connect_timeout_ms("ssid", "password", CYW43_AUTH_WPA2_AES_PSK, 10000))
  {
    printf("Erreur : Echec de la connection\n");
    return 0;
  }

  // Get our IP address in readable format
  printf("Connecté au réseau avec l'adresse %s\n", ipaddr_ntoa(((const ip_addr_t *)&cyw43_state.netif[0].ip_addr)));

  return 0;
}