Guide by Michael; Raspberry Pi Pico W | Connecting to the Internet

I have just shared content in Guides > Raspberry Pi Pico: “Raspberry Pi Pico W | Connecting to the Internet”





Read more

5 Likes

Hi Michael, got the PICO-W and followed this guide, but no go.
I don’t get connected;

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('ssid', 'password') # these set elsewhere
#adding the following line;
print(wlan.isconnected()) 

is always False
and ‘wlan.status()’ returns -2

using wlan.scan() I get
wlan [(b'mynetwork', b'\x807s\xc1\xef\xb8', 4, -37, 5, 9)]
which seems to show I have a security level 5, and the docs I have seen only refer to 4 levels.
Is this a red herring? Should I be looking at something else?
Thanks for your guide.
P
SOLVED
note the line
'wlan.connect(‘ssid’, ‘password’) ’
the quotes should not have been there.
Sorry to add to the noise.

5 Likes

No worries at all Peter,

Thanks for posting on the forum!

That is exactly what these forums are for, thank you for sharing the result, hopefully if someone else runs into something similar in the future they’ll find this.

Glad to hear it was just that there were strings in place of variable references, if you run into any other issues with the guide please let us know and we’ll see what we can do to help. Enjoy your weekend.

2 Likes

I have had my Pico W for just a day so still on a steep learning curve.
The channels allocated to wireless networks varies depending on the country so to avoid interference it is normal to set the country code. In 3.6.2 the guide https://datasheets.raspberrypi.com/picow/connecting-to-the-internet-with-pico-w.pdf suggests we should include:

import rp2
rp2.country('AU')

Interesting that in all the sample code I have looked at this is not included. Am I missing something?

1 Like

Hi Fractal,

I think it’s just a best practice snipet, if there aren’t a ton of routers around you should be fine to omit it (it seemed to have work just fine for Michael and has been working perfectly for me!)

1 Like

Michael,

I am new to Pico and also Python. This project was a great first step for me to begin learning - along with the tutorial on creating a web server to turn on/off an LED light and to read the position of the switch. Raspberry Pi Pico W | Create a Simple HTTP Server - Tutorial Australia

The project works well when I am in my local network. So I took it one step further and created a Port Forward from my router so that I and someone outside my home network could connect and turn on/off the LED that was connected to the Pico W.

This worked well the first time, but it only works once. After someone connects, I can’t then connect to the Pico W either locally or from outside my home using the public IP and port. I find myself needing to reboot the Pico W frequently to keep this functional.

Does anyone have a suggestion on how to add to the program to refresh the session so that it’s available for different users from different locations to log into the Pico W and access the webserver? Maybe reset the session after 2 minutes of inactivity and then listen for a new connection?

This will be a foundational step towards a next project that I am working on that will build upon this same functionality to let multiple people control a switch remotely.

Thanks so much. I am a complete first timer at learning to program and to work with a device like this. so just an apology if this is 101 level.

Paul

2 Likes

Update:

I tested again last night and established a connection in my local network using my mobile device. All worked dozens of times over the course of a few hours without a reboot. Then in the morning when i tested the webpage again , the buttons were not responsive- so it appears that the session ended - maybe the same concept of a session refresh will fix this?

I added the addition of turning the onboard LED on when the Pico connects to Wifi- this was helpful for when i took the device off the USB connection and had it running as a standalone device on an indepe3ndent power source. It was very helpful to see when a connection was made. I need to learn how to determine if it is lost, and then have the Led turn off next :slight_smile:

Looking forward to any suggestions and pointers or solutions that others may have found to get better consistency and more flexibility for multiple users to access the Pico via wifi.

Paul

1 Like

If you are running something important and don’t want just anyone to have access, make sure you set up security. When something is visible on the internet, anyone, anywhere with internet access can hack into it.

Cheers
Jim

2 Likes

Thanks for putting this together @Michael, the Pico W arrived today and following the tutorial gives confidence it is functioning correctly. Now what can I do with a Pico that has WiFi … hmmm
Cheers
Jim

3 Likes

The Pico W has WiFi and RTC. An event such as reading a sensor will usually need a date/time stamp so setting the RTC is important. It would have been expected that the Pico would have a MicroPython method to set the time using NTP but I could not find one. In the class machine.RTC the only method available to get or set the time is:
RTC.datetime([datetimetuple])
where the 8-tuple has the format (year, month, day, weekday, hours, minutes, seconds, subseconds). Just to add to confusion note the RP2 quick reference for the RTC is actually wrong!
https://docs.micropython.org/en/latest/rp2/quickref.html#real-time-clock-rtc

So setting and reading the RTC looks like:

rtc = machine.RTC()
rtc.datetime((2022, 9, 1, 5, 22, 05, 36, 0))
print(rtc.datetime())

I did develop a method to set the RTC but it is clunky and I am hoping that users can offer more efficient ways of doing this.

Firstly on my webserver I wrote a PHP script called timestamp.php to provide the date/time in JSON format. The MicoPython method demands integers with no leading zeros so you need intval().

<? 
date_default_timezone_set("UTC");
$myObj = new stdClass();
$myObj->year = intval(date(Y));
$myObj->month = intval(date(n));
$myObj->day = intval(date(j));
$myObj->dayofweek = intval(date(N));
$myObj->hours = intval(date(G));
$myObj->mins = intval(date(i));
$myObj->secs = intval(date(s));
$myObj->subseconds = 0;
$myJSON = json_encode($myObj);
echo $myJSON;
?>

For the Pico I wrote a MicroPython script to read the JSON date/time and set the RTC.

# It is assumed the Pico is connected to WiFi
import urequests
import json
rtc = machine.RTC()
r = urequests.get("https://www.myserver.com/timestamp.php")
print("r.text: " + str(r.text))
j = json.loads(r.text)
rtc.datetime((j["year"], j["month"], j["day"], j["dayofweek"], j["hours"], j["mins"], j["secs"], j["subseconds"]))
print(rtc.datetime())

The print statements output:

r.text: {"year":2022,"month":9,"day":1,"dayofweek":4,"hours":12,"mins":53,"secs":33,"subseconds":0}
(2022, 9, 1, 3, 12, 53, 33, 0)

There has to be a better way! Anyone?

3 Likes

Note in the above if Core Electronics or anyone wants to publish the PHP script on their webserver that is fine. I use UTC for storing events swapping to local time for display. If you want local time change ‘UTC’ to say ‘Australia/Sydney’.

Edit: An enthusiastic volunteer with a public webserver could actually publish a script for all the time zones e.g. utc.php, nsw.php, vic.php etc.

2 Likes

Excellent write up on the Pico and RTC.
I don’t think there is a better way given the limitations of the Pico.

Initially I was excited by the Pico, low price and easy to use with Python and Thonny. But looking deeper it has some limitations. The 2MB memory of which the Micro Python interpreter takes up half and Circuit Python over half means many nice to have features of Python are missing.

I think they have done an excellent job fitting python into just 1MB.

I think the Pico versions by Pimoroni and WIZnet are headed down the right path by providing 16MB of memory. I was disappointed when the Pico W came with only 2MB. it would have been an excellent opportunity to up the memory capacity.

The work done to get the Pico on the Arduino IDE is excellent, compiling a C++ program and running on the Pico would make more memory available. The interpretive nature of Python is a limitation when a program may not be using many features of Python but the feature are still there in memory.

Still a board for less than $10 AU with WiFi is great.

Cheers
Jim

2 Likes

The memory usage by Micro Python in my previous post is incorrect.

Micro Python Pico, Free space 1.4MB.
Micro Python Pico W, Free space 848KB.

I think it is even more amazing Micro Python takes up only 600KB.
But the addition of WiFi takes up a huge amount of memory giving weight to the need for more memory, at least 4MB.

Probably the uses the Pico W will be put to, mean it will have enough.
I just remember my experience with the micro:Bit and running out of memory, a situation the Make Code programming software could not handle nicely.

Regards
Jim

3 Likes

@fractal have a look for NTP and/or adding an external RTC.
picoW NTPClient has a few comments about both.
I have found that some NTP clients have trouble with Daylight saving in the Southern Hemisphere (I think it was ESP32), but it just needed manual adjusting from +10h to +11h when appropriate.
Dave

1 Like

Hi Jim

With regard to the external 2MB flash RAM on my current project the sum of main.py and the associated libraries are only of the order of 15KB so I do not think that will be a challenge.

What is of concern is the on-chip 264KB RAM which is used by the python interpreter, stack, buffers, etc. When a module is imported, MicroPython compiles the code to bytecode which is also stored in RAM. My current project takes measurements which are stored on a central server. If the WiFi or internet fails it buffers measurements until the network restores. I am worried regarding how much RAM will be available for buffering.

There is an article devoted to how to reduce RAM usage and part of that involves writing efficient code.
https://docs.micropython.org/en/latest/reference/constrained.html#ram

4 Likes

Hi Dave

The Pico W has an inbuilt RTC so you do not need an external one. In the above code I was able to set the RTC and get the time.

Using local time zones is problematic for measurements. For example during daylight saving changeover there will be an hour of no measurements or an hour of duplicates. I always use UTC for measurement and then use the local time zone to display data.

Now have SNTP working using pool.ntp.org port 123 with the following code. Note it assumes working WiFi and internet access. It is for UTC, if you want a local time zone then adjust NTP_DELTA. I am assuming the RTC will drift so have now written set_time() as a function so it can be called every 24 hours.

import machine
import socket
import struct
import time

# The below code assumes WiFi is working and there is a connection to the internet
NTP_DELTA = 2208988800
rtc = machine.RTC()

def set_time():
    NTP_QUERY = bytearray(48)
    NTP_QUERY[0] = 0x1B
    addr = socket.getaddrinfo("pool.ntp.org", 123)[0][-1]
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        s.settimeout(1)
        res = s.sendto(NTP_QUERY, addr)
        msg = s.recv(48)
    finally:
        s.close()
    val = struct.unpack("!I", msg[40:44])[0]
    t = val - NTP_DELTA    
    tm = time.gmtime(t)
    machine.RTC().datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0))

set_time()
print(rtc.datetime())
4 Likes

Sorry, I must have misread somewhere. I thought you couldn’t find the NTPclient and were having trouble with the internal RTC loosing time, so suggested an external one and the NTP client.

Dave.

2 Likes

So the Pico W is taking a measurement every minute and sleep(60) will do that. But supposing you wanted take a measurement precisely on the minute! Somewhat surprising but MicroPython will easily do that. The following code assumes that the RTC is set. When you run the code do not be alarmed if nothing happens - it is waiting for the minute to tick over.

from time import sleep
while True:
    r = rtc.datetime()
    delay = 60 - r[6]
    sleep(delay) # wait for new minute
    r = rtc.datetime()
    today = '{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}'.format(r[0], r[1], r[2], r[4], r[5], r[6])    
    print(today)

Here is what the result looks like using a PiicoDev TMP117 for temperature and PiicoDev BME280 for pressure and humidity. Note the measurement is exactly on the minute (UTC of course).

2022-09-05 10:38:00 21.7°C 1006.7hPa 51.3%RH
2022-09-05 10:39:00 21.6°C 1006.7hPa 51.3%RH
2022-09-05 10:40:00 21.6°C 1006.7hPa 51.3%RH
2022-09-05 10:41:00 21.6°C 1006.7hPa 51.4%RH
2022-09-05 10:42:00 21.6°C 1006.7hPa 51.4%RH
2022-09-05 10:43:00 21.6°C 1006.8hPa 51.5%RH
2022-09-05 10:44:00 21.5°C 1006.8hPa 51.4%RH
2022-09-05 10:45:00 21.5°C 1006.8hPa 51.4%RH
2022-09-05 10:46:00 21.5°C 1006.8hPa 51.8%RH
2022-09-05 10:47:00 21.5°C 1006.8hPa 51.5%RH
2022-09-05 10:48:00 21.5°C 1006.8hPa 51.5%RH
2022-09-05 10:49:00 21.5°C 1006.8hPa 51.6%RH
3 Likes

Hey @Paul210700, you might want to look into RPi’s Connecting to the Internet document: Chapter 3.9.3. An asynchronous web server.
This is a much more robust way to create a server, which will also handle multiple requests asynchronously.

3 Likes

Michael,
Not sure this was the place to ask, but do you have card with the Pico W pinouts like this?

Except that one is 5% too big :wink: ( maybe the next print run will be better) it should only be 2 inches long, not 2.1.

2 Likes