0

Challenger RP2040 WiFi with U.FL connector

The Challenger RP2040 WiFi is an Arduino/Micropython compatible Adafruit Feather format micro controller board based on the Raspberry Pico chip.

When we designed this board we took our existing Challenger M0 WiFi board and replaced the SAMD21 micro controller with the extremely powerful dual core RP2040 Cortex-M0 device. So the main controller of this board is the RP2040 which has 264KByte of SRAM internally and 8MByte of external FLASH memory.

WiFi

Just like the Challenger M0 WiFi it has a  ESP8285 WiFi chip. For those of you that is unfamiliar with this device, it is basically an ESP8266 device with an integrated 1MByte of flash memory. This allows us to have an AT command interpreter inside this chip that the main controller can talk to and connect to you local WiFi network. The communications channel between the two devices is an unused UART on the main controller and the standard UART on the ESP8285. As simple as it can be.

The ESP8285 chip comes pre-flashed with Espressif’s AT command interpreter stored in the internal 1MByte of the ESP8285. This interpreter support most of the operating and sleep modes of the standard ESP8266 framework which makes it easy to work with. Talking to the device is as easy as opening the second serial port (Serial2), resetting the ESP8285 and start listening for events and sending commands

USB Type C

In the recent years we have noticed that we are seeing more and more USB Type C cable laying around the lab due to the fact that all new phones and accessories use them. As of yet we haven’t seen any shortage of micro USB cables but we are not getting any new ones any more and old ones do break occasionally. So we decided to go for a USB Type C connector for this board. A bonus of this is that they are quite bit more durable and you don’t have to fiddle with the cable before plugging it in.

Pinout

On board antenna or U.FL ?

This board is available in two different antenna option versions. The most common version is with an on board chip antenna which just works straight out of the box. The second version has a U.FL connector on board which requires you to add an external antenna for your system. You can basically use any 50ohm 2.45GHz antenna and it will work just fine.

Weight 0.009 kg
Dimensions 5.07 × 2.28 × 0.72 cm

Using the Arduino environment

We’ve teamed up with Earle F. Philhower over at his Github page to provide Arduino support for our Raspberry Pi Pico based boards. All instructions on how to install the board support packaged as well as multiple examples on how to use the Raspberry Pi Pico processor.

MicroPython

The Challenger RP2040 WiFi board is fully compatible with both the micropython package found at the Raspberry Pi site as well as Adafruits CircuitPython. Instruction are available on how to install the python interpreter of your choice is available on respective web site.

Short initialization example

To simplify the hardware aspect of the WiFi modem we have included a small helper class in the Arduino IDE that is always available to you as a developer. This new class replaces the previous examples on how to do a proper reset and sync.

The first thing you need to do in your sketch is to include the support library by entering:

#include <ChallengerWiFi.h>

After this basically all you need to do before starting the WiFi manager is the following:

if (Challenger2040WiFi.reset())
    Serial.println(F("WiFi Chip reset OK !"));
else
    Serial.println(F("Could not reset WiFi chip !"));

After these step the modem is initialized and is ready to accept your commands. The reset() function of the built in Challenger2040WiFi library will perform a HW reset of the WiFi modem and wait for it to return the “ready” prompt. After this a WiFi manager can be started and start communicating with the modem. Here at iLabs we use the WiFiEspAT library and initializing the stack is as easy as

WiFi.init(Serial2);

Make sure the library is included at the top of the file with:  #include <WiFiEspAT.h>

At this point you can also do a check to make sure that the data link is setup properly.

if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
}

You are now good to go, so doing something like this:

Serial.println("Waiting for connection to WiFi");
while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print('.');
}
Serial.println();
Serial.println("Connected to WiFi network.");

will work as expected.

Changing the baudrate

The default baudrate between the RP2040 micro controller and the ESP8285 WiFi modem is 115200 and while this is probably good for most IoT applications that normally don’t send very much data it can sometimes be useful to increase the baudrate. The Challenger2040WiFi contains a method for doing this and again it is super simple to use. Just do the following and the baud rate will be altered on both systems and the devices will be synced up.

Challenger2040WiFi.changeBaudRate(921600);

After this you can proceed to communicate with the device as normal.

Sending and AT command

After the modem has been initialized and it has reported that it is ready you can now send a command to it. Here’s an example on how a simple command can be sent.

Serial2.println("ATE0");

This command simply tells the modem not to repeat everything back that you send to it. If you want to enable this again you would simply send the following command:

Serial2.println("ATE1");

Pass through example

This example Arduino program creates a USB2Serial pass through to the ESP8285. This can be used to flash the ESP with new upgraded software or you can write your own code and use this short snippet to flash the device.

/*
  Challenger USB to serial port.

  This is an example on how to flash the onboard ESP8285.
  TinyUSB must be selected in the Arduino IDE for this sketch to work.

  The ESP8285 should to flashed with the following command:
  esptool.py --port <port> --baud <rate> write_flash -e -fm dout -fs 1MB <filename.bin>

  This program must be compiled with tinyUSB to work.
*/

#include <Arduino.h>

#ifdef USE_TINYUSB
#include <Adafruit_TinyUSB.h>
#define USE_OVERRIDE_LINE_STATE_CB 1
#endif

// Sets the level of debug info that is printed on the serial output
// 0 = No debug information at all
// 1 = Basic debug information
// 2 = Full debug information
#define DEBUG_LVL 0

#define ESP_PORT Serial2
#define PC_PORT Serial
#define DEBUG_PORT Serial1

#define PACKET_SIZE 64

int led = LED_BUILTIN; // the PWM pin the LED is attached to
int led_state = 0;
int wifi_rst = 19;
int wifi_mode = 13;
uint32_t baud_rate = 115200;
static int port = -1;
static int words = 0;
uint8_t ch;
char buffer[PACKET_SIZE];
size_t received;

void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* coding) {
  (void) itf;
#if DEBUG_LVL >= 1
  DEBUG_PORT.printf("n");
#endif 
  if (coding->bit_rate != baud_rate) {
    ESP_PORT.begin(coding->bit_rate);
    baud_rate = coding->bit_rate;
#if DEBUG_LVL >= 1
    DEBUG_PORT.printf("Setting new baudrate to %d ", baud_rate);
#endif 
  }
}

//
// This overrides the stack functionality to capture cdc line state
// changes.
//
#if defined(USE_OVERRIDE_LINE_STATE_CB)
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
  (void) itf; // interface ID, not used

  if (rts) {
    digitalWrite(wifi_rst, LOW);
#if DEBUG_LVL >= 1
    DEBUG_PORT.printf("RST=low ");
#endif 
  } else {
    digitalWrite(wifi_rst, HIGH);
#if DEBUG_LVL >= 1
    DEBUG_PORT.printf("RST=high ");
#endif 
  }

  if (dtr) {
    digitalWrite(wifi_mode, LOW);
#if DEBUG_LVL >= 1
    DEBUG_PORT.printf("MODE=low");
#endif 
  } else {
    digitalWrite(wifi_mode, HIGH);
#if DEBUG_LVL >= 1
    DEBUG_PORT.printf("MODE=high");
#endif 
  }
#if DEBUG_LVL >= 1
  DEBUG_PORT.printf("n");
#endif

// DTR = false is counted as disconnected
  if (!dtr) {
// touch1200 only with first CDC instance (Serial)
    if (itf == 0) {
      cdc_line_coding_t coding;
      tud_cdc_get_line_coding(&coding);

      if (coding.bit_rate == 1200) {
        TinyUSB_Port_EnterDFU();
      }
    }
  }
}
#endif

// the setup routine runs once when you press reset:
void setup()
{
  pinMode(led, OUTPUT);
  digitalWrite(led, 0);

#if DEBUG_LVL >= 1
  DEBUG_PORT.begin(921600);
  DEBUG_PORT.println("nnnnnnDebug monitor !");
#endif

// Set default baudrates
  ESP_PORT.begin(baud_rate);
  ESP_PORT.setTimeout(10);

  PC_PORT.begin(baud_rate);
  PC_PORT.setTimeout(10);

// Set initial state of control pins
// Normal start when the reset pin is released
  digitalWrite(wifi_rst, LOW);
  pinMode(wifi_rst, OUTPUT);
  digitalWrite(wifi_mode, HIGH);
  pinMode(wifi_mode, OUTPUT);
// delay(1);
// digitalWrite(wifi_rst, HIGH);

  while (!PC_PORT);
  digitalWrite(led, HIGH);
}

//
// The main loop were data is received from the host and then forwarded
// to the ESP8285 and vice versa.
//
void loop() {

  // Handle data from the USB port ment for the ESP8285
  if (PC_PORT.available()) {
    received = PC_PORT.readBytes(buffer, PACKET_SIZE);
    ESP_PORT.write(buffer, received);

#if DEBUG_LVL >= 2
    if (port != 1) {
      port = 1;
      words = 0;
      DEBUG_PORT.println("nFrom USB to ESP8285 ==================================");
    }
    for (int i=0;i<received;i++) {
      DEBUG_PORT.printf("%02x ", buffer[i]);
      if (++words > 15) {
        words = 0;
        DEBUG_PORT.println();
      }
    }
#endif
  }

  // Handle response data from the ESP8285
  if (ESP_PORT.available()) {
    received = ESP_PORT.readBytes(buffer, PACKET_SIZE);
    PC_PORT.write(buffer, received);

#if DEBUG_LVL >= 2
    if (port != 2) {
      port = 2;
      words = 0;
      DEBUG_PORT.println("nFrom ESP8285 to USB ==================================");
    }
    for (int i=0;i<received;i++) {
      DEBUG_PORT.printf("%02x ", buffer[i]);
      if (++words > 15) {
        words = 0;
        DEBUG_PORT.println();
      }
    }
#endif
  }
}

Complete example

This example will connect to Arduino’s website and get an Arduino logo and display it in the log window:

/*
Web client

This sketch connects to a website (http://arduino.cc)
using the WiFi module.

created 13 July 2010
by dlf (Metodo2 srl)
modified 31 May 2012
by Tom Igoe
modified in Jul 2019 for WiFiEspAT library
by Juraj Andrassy https://github.com/jandrassy
*/
#include <WiFiEspAT.h>
#ifdef USE_TINYUSB
#include <Adafruit_TinyUSB.h>
#define USE_OVERRIDE_LINE_STATE_CB 1
#endif
#include <ChallengerWiFi.h>

///////please enter your sensitive data in the Secret tab/arduino_secrets.h
const char ssid[] = "<your-ssid>"; // your network SSID (name)
const char pass[] = "<your-password>"; // your network password (use for WPA, or use as key for WEP)

#define AT_BAUD_RATE 115200

const char* server = "arduino.tips";

WiFiClient client;

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, 0);

Serial.begin(115200);

while (!Serial) // Wait for the log window to be started
delay(10);

Serial2.begin(115200);
if (Challenger2040WiFi.reset()) {
Serial.println(F("WiFi Chip reset OK !"));
} else {
Serial.println(F("Could not reset WiFi chip !"));
while(1);
}

Serial.println("ESP8285 Wifi test program started !");

digitalWrite(LED_BUILTIN, HIGH);

WiFi.init(Serial2, PIN_ESP8285_RST);

if (WiFi.status() == WL_NO_MODULE) {
Serial.println();
Serial.println("Communication with WiFi module failed!");
// don't continue
while (true);
}

Serial.println();
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);

int status = WiFi.begin(ssid, pass);

Serial.print("Status: ");
Serial.println(status);

if (status == WL_CONNECTED) {
Serial.println();
Serial.println("Connected to WiFi network.");
printWifiStatus();
} else {
WiFi.disconnect(); // remove the WiFi connection
Serial.println();
Serial.println("Connection to WiFi network failed.");
}

// waiting for connection to Wifi network set with the SetupWiFiConnection sketch
Serial.println("Waiting for connection to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print('.');
}
Serial.println();
Serial.println("Connected to WiFi network.");

Serial.println("Starting connection to server...");
if (client.connect(server, 80)) {
Serial.println("connected to server");
client.println("GET /asciilogo.txt HTTP/1.1");
client.print("Host: ");
client.println(server);
client.println("Connection: close");
client.println();
client.flush();
}
}

void printWifiStatus() {

// print the SSID of the network you're attached to:
char ssid[33];
WiFi.SSID(ssid);
Serial.print("SSID: ");
Serial.println(ssid);

// print the BSSID of the network you're attached to:
uint8_t bssid[6];
WiFi.BSSID(bssid);
Serial.print("BSSID: ");
printMacAddress(bssid);

uint8_t mac[6];
WiFi.macAddress(mac);
Serial.print("MAC: ");
printMacAddress(mac);

// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

void printMacAddress(byte mac[]) {
for (int i = 5; i >= 0; i--) {
if (mac[i] < 16) {
Serial.print("0");
}
Serial.print(mac[i], HEX);
if (i > 0) {
Serial.print(":");
}
}
Serial.println();
}

void loop() {

// if there are incoming bytes available
// from the server, read them and print them
while (client.available()) {
char c = client.read();
Serial.write(c);
}

// if the server's disconnected, stop the client
if (!client.connected()) {
Serial.println();
Serial.println("disconnecting from server.");
client.stop();

// do nothing forevermore
while (true);
}
}

CircuitPython by Adafruit

The Challenger boards fully supports circuitpython and should be supported shortly by the official releases. But until then we have created a beta release of the circuitpython image which can be downloaded from here.

Please go ahead and put it through its paces and feel free to report back any issues that you may find.

How do I use it

Basically it works as any other circuitpython board but we have included relevant board parameters for simplify accessing specific pins and other special IO’s. The board help function lists the following functions:

object <module 'board'> is of type module
__name__ -- board
board_id -- challenger_rp2040_wifi
SDA -- board.SDA
GP0 -- board.SDA
SCL -- board.SCL
GP1 -- board.SCL
D5 -- board.D5
GP2 -- board.D5
D6 -- board.D6
GP3 -- board.D6
ESP_TX -- board.ESP_TX
GP4 -- board.ESP_TX
ESP_RX -- board.ESP_RX
GP5 -- board.ESP_RX
D9 -- board.D9
GP6 -- board.D9
D10 -- board.D10
GP7 -- board.D10
D11 -- board.D11
GP8 -- board.D11
D12 -- board.D12
GP9 -- board.D12
D13 -- board.D13
GP10 -- board.D13
NEOPIXEL -- board.NEOPIXEL
GP11 -- board.NEOPIXEL
LED -- board.LED
GP12 -- board.LED
WIFI_MODE -- board.WIFI_MODE
WIFI_RESET -- board.WIFI_RESET
D0 -- board.D0
TX -- board.D0
GP16 -- board.D0
D0 -- board.D0
TX -- board.D0
GP17 -- board.D0
SCK -- board.SCK
GP22 -- board.SCK
MOSI -- board.MOSI
GP23 -- board.MOSI
MISO -- board.MISO
GP24 -- board.MISO
A0 -- board.A0
GP26 -- board.A0
A1 -- board.A1
GP27 -- board.A1
A2 -- board.A2
GP28 -- board.A2
A3 -- board.A3
GP29 -- board.A3
A4 -- board.A4
GP25 -- board.A4
A5 -- board.A5
GP21 -- board.A5
I2C -- <function>
SPI -- <function>
UART -- <function>

Using these defines it is now simple to access the serial port that interfaces to the WiFi modem.

import board
import busio
import digitalio

wifi=busio.UART(board.ESP_TX, board.ESP_RX, baudrate=115200, receiver_buffer_size=2048)
wrst = digitalio.DigitalInOut(board.WIFI_RESET)
wmde = digitalio.DigitalInOut(board.WIFI_MODE)
wrst.direction = digitalio.Direction.OUTPUT
wmde.direction = digitalio.Direction.OUTPUT
wrst.value = 0
wmde.value = 1
wrst.value = 1

Reading from the serial line at this point will read in a garbage string generated by the WiFi modem. So typing this:

print (wifi.read())

Will produce a bytearray that looks like this:

b'sx88x03x00lx9cxc8sOx80Flxe0xf1o@x03Fxf0x06x8cxc6x0cx8ex83xecx8exx8cxbex8fx83Ox80vx9cx81x9bO|x13cx8cx8epx0cx88x0cxf3ooxf6x03Fxefxf9oxc6x93Nxf3x06cx1cpx84x8fxb1l`tx9b`tx83ggxe0Ao@x03Gxf8x83Gxe06x87xc0x0cx8ex80x0cx8ex80'

You can discard this string as it is simply a startup message from the modem that looks like garbage. If we now instead send a simple AT command to the modem like this:

wifi.write(bytearray('ATrn'))

You should now receive a valid response back from the modem when reading. It should look like this:

print (wifi.read())
b'ATrnrnOKrn'

Initializing the board in circuitpython using Adafruit espatcontrol library

The following piece of startup code is taken from Adafruits espatcontrol python library examples and modified to support our board. You

if board.board_id == "challenger_rp2040_wifi":
RX = board.ESP_RX
TX = board.ESP_TX
resetpin = DigitalInOut(board.WIFI_RESET)
rtspin = False
uart = busio.UART(TX, RX, baudrate=11520, receiver_buffer_size=2048)
esp_boot = DigitalInOut(board.WIFI_MODE)
esp_boot.direction = Direction.OUTPUT
esp_boot.value = True
else:
RX = board.ESP_TX
TX = board.ESP_RX
resetpin = DigitalInOut(board.ESP_WIFI_EN)
rtspin = DigitalInOut(board.ESP_CTS)
uart = busio.UART(TX, RX, timeout=0.1)
esp_boot = DigitalInOut(board.ESP_BOOT_MODE)
esp_boot.direction = Direction.OUTPUT
esp_boot.value = True
# For Boards that do not have an rtspin like challenger_rp2040_wifi set rtspin to False.
esp = adafruit_espatcontrol.ESP_ATcontrol(uart, 115200, reset_pin=resetpin, rts_pin=rtspin, debug=debugflag
)
print("Resetting ESP module")
esp.hard_reset()

And you are good to go. Happy snaking around the system and feel free to report any bugs that you may find.


Download CircuitPython

Documentation for the Challenger RP2040 WiFi board.

You can always get our products from your local reseller if you like. Here is a list of current resellers.

    • The Pi Hut Raspberry Pi Superstore

 

  • The largest maker shop in Switzerland

Check out this informative video with detailed information about the board.

Reviews

There are no reviews yet.

Be the first to review “Challenger RP2040 WiFi with U.FL connector”