Problems with Wifi Shield

I am having problems with the Wifi shield.

Most of the examples in the IDE work except that tcp_client_1.py returns no data, and any other socket server I have tried returns no data,or returns random data.

I am trying to send an http message to a node red server when I detect a face. It occasionally works once, never twice, and never when I use it in my intended way.

This is the code:

def say(): 
    client = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)

    try:      
        client.connect(('192.168.0.101', 1880))
        client.settimeout(5.0)
    except OSError as er:
        print("Error from connect: " + str(er))
        
    try:
        client.send("GET /camera?say=Hello HTTP/1.0\r\n\r\n")
        reply = client.recv(128).decode("utf-8")
    except OSError as er:
        print("Error from send: " + str(er))
        
    client.close()

I usually get error 116 from send on the first call, and error -9 from connect on subsequent calls.

Am I doing something wrong. Are the OS errors listed anywhere?

Do you get errors/exceptions when trying tcp_clinet.py ? It shouldn’t return any data just an empty string.
Also you should make sure the module is connected, it should print some info after “Trying to connect…” (BSSI, SSID, mac, and IP) does it print that ?

Error numbers are the same ones in errno.h (except -1 is an internal error in the sockets library).

116 is timeout (should actually be negative)
-9 is a bad FD, probably closed or not bound for a server socket.

umm so there’s a bug in the recv function, it doesn’t return the number of bytes which causes the higher level wrapper to think it got 0 bytes. I’m going to fix this in the next release, but since you’re working on something right now I’m attaching a patched firmware, this firmware image also has debugging printf’s enabled to help us debug if there are more issues with the WiFi/sockets code.
OMV2-RECV-FIX.zip (1.32 MB)

I tried to use your new firmware by unzipping in and selecting the bin file in the “Run Bootloader” IDE option. It appeared to work, but the IDE will not let me connect to the device unless I upgrade the firmware, which I assume will put it back to the release version. Is there any way round this?

I should not be getting the bad FD response, as you can see from my code that I have just created the socket and it is a client socket.

The 116 errors occur randomly but most of the time on nearly any web site. The value is positive.

I think the bad FD response happens on all connect calls after the 116 error has occurred, even when a new socket is created.

(If I just close a socket and then attempt a new connect on the same socket, I get a -6 response).

In tcp_client_1.py, if I change the web site from “www.google.com” to “www.bbc.co.uk” (for example), I get the 116 error.

Hi, to get around the IDE issue there’s a file in the IDE dir called share/QtCreator/firmware/version.txt. Make the version number 2.0.0.

It could be another issue with the FW, please try the patched FW image (you can edit the firmware.txt file to bypass the IDE check just like Kwabena mentioned), the patched FW prints some debugging message, if you’re still having issues send me the log and I’ll look into it.

Hi the new firmware fixed the problem with the reply in tcp_client_1.py. I am now getting HTML back, although it is slightly odd what it prints:

Trying to connect… (may take a while)…
[-56, 2, ‘virginmedia6527155’, ‘f8:f0:05:f6:83:b5’, ‘192.168.0.19’]
socket_callback(): connect success.

\r\n'

I still have the other two problems:

[-52, 2, ‘virginmedia6527155’, ‘f8:f0:05:f6:83:b5’, ‘192.168.0.19’]
socket_callback(): connect success.
wifi_callback(): Unknown message type: 27
Error from send: 116

and

Error from connect: -9

In the second case, there is no other diagnostics.

The code is still as above. The first case is where I call say() at the start of the program. The second is when I call it after detecting a face.

Hi, the tcp_client.py prints the whole page at least when I run it here, the output looks like this:

wifi_callback(): Unknown message type: 27
socket_callback(): connect success.
socket_callback(): recv 479
b'HTTP/1.0 302 Found\r\nCache-Control: private\r\nContent-Type: text/html ....

I think in the first case recv is timing out, your exception handler is around send/recv so I’m not sure which one is failing… Anyway, most calls were set to timeout after 1000ms regardless of the timeout set with settimeout(), I fixed this issue now to use the timeout passed in settimeout(), passing 0 means block forever. I’m attaching another FW image.

I’m not sure about the second case (-9), I get -9 when the socket is closed, anyway, please post the whole script again after testing this fw image.
firmware.bin.zip (674 KB)

I am still getting the same errors, even with a high timeout. The error is now being reported as -116 (i.e negative).

I have changed the script slightly. Here is the full script:

import sensor, time, image,pyb, sys
import network, usocket

# AP info
SSID='virginmedia6527155' # Network SSID
KEY='********  # Network key

wlan = network.WINC()
wlan.connect(SSID, key=KEY, security=wlan.WPA_PSK)
print(wlan.ifconfig())

def say():
    client = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)

    try:
        client.connect(('192.168.0.101', 1880))
        client.settimeout(20.0)
        try:
            client.send("GET /camera?say=Hello HTTP/1.0\r\n\r\n")
            reply = client.recv(256).decode("utf-8")
            print(reply)
        except OSError as er:
            print("Error from send: " + str(er))

    except OSError as er:
        print("Error from connect: " + str(er))

    client.close()

say()

s1 = pyb.Servo(1) # P7
s2 = pyb.Servo(2) # P8

sw = 240
sh = 160

x_angle = 0
y_angle = -30

def blink():
    led = pyb.LED(2) # Use green LED.

    led.on()
    time.sleep(150)
    led.off()
    time.sleep(100)
    led.on()
    time.sleep(150)
    led.off()

# Reset sensor
sensor.reset()

# Sensor settings
sensor.set_contrast(1)
sensor.set_gainceiling(16)
# HQVGA and GRAYSCALE are the best for face tracking.
sensor.set_framesize(sensor.HQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)

# Load Haar Cascade
# By default this will use all stages, lower satges is faster but less accurate.
face_cascade = image.HaarCascade("frontalface", stages=25)

# FPS clock
clock = time.clock()

# Flip display
sensor.__write_reg(0x0C, sensor.__read_reg(0x0C) | (1 << 7))

while (True):
    s1.angle(y_angle)
    s2.angle(x_angle)
    clock.tick()

    # Capture snapshot
    img = sensor.snapshot()

    # Find objects.
    # Note: Lower scale factor scales-down the image more and detects smaller objects.
    # Higher threshold results in a higher detection rate, with more false positives.
    objects = img.find_features(face_cascade, threshold=0.5, scale=1.5)

    if objects:
        blink()
        say()

    # Draw objects
    for r in objects:
        img.draw_rectangle(r)
        print(r)
        w = (sw - r[2])/2
        h = (sh - r[3])/2
        x_angle -= (w - r[0])/10
        y_angle -= (h - r[1])/10

Here is the output when the first call to say() worked:

[-50, 2, ‘virginmedia6527155’, ‘f8:f0:05:f6:83:b5’, ‘192.168.0.19’]
socket_callback(): connect success.
wifi_callback(): Unknown message type: 27
socket_callback(): recv 195
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Length: 2
Content-Type: text/html; charset=utf-8

ETag: W/“2-REvLOj/Pg4kpbElGfyfh1g”
Date: Tue, 11 Oct 2016 07:04:27 GMT
Connection: close

ok
Error from connect: -9
(66, 30, 122, 122)
Error from connect: -9
(30, 3, 81, 81)

And here is output when it failed:

[-51, 2, ‘virginmedia6527155’, ‘f8:f0:05:f6:83:b5’, ‘192.168.0.19’]
socket_callback(): connect success.
wifi_callback(): Unknown message type: 27
Error from send: -116
Error from connect: -9
(53, 10, 122, 122)
Error from connect: -9
(56, 5, 122, 122)

In all cases the call of say() after face detection fails on connect with error -9.

I think I see the problem…You can’t use the WiFi shield and servos at the same time, the WiFi shield uses all pins except UART/I2C on the left header. That’s why the first say() works because it’s called before changing I/Os to PWM, you could confirm that by commenting the servo. If you must use WiFi + servos you could use UART/I2C to another board control them.

It works slightly better with the servos commented out.

The initial say() still fails most of the time with the -116 error. And if it fails, all subsequent calls to say() fail. Like this:

[-47, 2, ‘virginmedia6527155’, ‘f8:f0:05:f6:83:b5’, ‘192.168.0.19’]
socket_callback(): connect success.
wifi_callback(): Unknown message type: 27
Error from send: -116
socket_callback(): connect error!
Error from send: -9
(91, 7, 81, 81)

If I keep trying the first call to say() occasionally works, and if it does all subsequent calls work. It seems to work about 1 in 5 times. The timeout does not seem to matter. It works as well with timeout 1.0 as any other value.

I did not realise that the Wifi shield would stop other things from working. (Perhaps I should have guessed, and checked). It will make the project I want to do harder.

A version of OpenMV based in an ESP32, with Wifi and Bluetooth built-in, would be good, if that were possible.

Unfortunately the code doesn’t detect conflicts it just lets you do whatever you want, maybe this should be fixed. Anyway, one of the PWM pins is connected to the WiFi shield reset pin, probably why you get bad FD. There’s another timer on P4 and P5 (the unused pins) but it’s not currently used for servos, will see if I can enabled those in the next FW release.

We’re working on an M7 cam, 216MHz dual issue, 512KBs SRAM + SDRAM, HW JPEG and it has more I/Os.

Did you see from my previous reply that I am still having problems with the Wifi shield even when I don’t use the servos. I can only connect to my web site about 1 in 5 times, and when it fails, it fails all subsequent times, until I restart the program.

Nope, I missed it, I’ll test your script now without servos.

The problem of the -116 error has not been fixed by any of your changes or by not using servos. Setting a timeout bigger than 1.0 does not make connection work any better, it just makes it fail slower.

So I tested your script using the following host side script:

import sys, socket
HOST = ''   # Symbolic name, meaning all available interfaces
PORT = 1880 # Arbitrary non-privileged port
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print ('Socket created')
 
#Bind socket to local host and port
try:
    s.bind((HOST, PORT))
except socket.error as msg:
    print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
    sys.exit()
     
print ('Socket bind complete')
 
#Start listening on socket
s.listen(10)

#now keep talking with the client
while 1:
    try:
        #wait to accept a connection - blocking call
        print("Waiting for connections...")
        client, addr = s.accept()
        client.settimeout(5.0)
        print('Connected to ' + addr[0] + ':' + str(addr[1]))
        data = client.recv(1024)
        client.send("Hello from server!")
        client.close()
    except socket.error as msg:
        print ('Connection failed. Error: ' + str(msg))
        client.close()
     
s.close()

I noticed that only the first say() fails, then it runs normally, adding a delay after connect to network seems to make the first say() work, not sure why, will look into it further but for now you could just remove the first say(), also made small changes to the script :

import sensor, time, image,pyb, sys
import network, usocket

# AP info
SSID=''     # Network SSID
KEY=''      # Network key

wlan = network.WINC()
wlan.connect(SSID, key=KEY, security=wlan.WPA_PSK)
print(wlan.ifconfig())

def say():
    try:
        client = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)
        client.connect(('192.168.0.101', 1880))
        client.settimeout(2.0)        
        client.send("GET /camera?say=Hello HTTP/1.0\r\n\r\n")
        reply = client.recv(256).decode("utf-8")
        client.close()
        print(reply)
    except Exception as e:
        print("Error : " + str(e))

def blink():
    led = pyb.LED(2) # Use green LED.

    led.on()
    time.sleep(150)
    led.off()
    time.sleep(100)
    led.on()
    time.sleep(150)
    led.off()

# Reset sensor
sensor.reset()

# Sensor settings
sensor.set_contrast(1)
sensor.set_gainceiling(16)
# HQVGA and GRAYSCALE are the best for face tracking.
sensor.set_framesize(sensor.HQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
# Flip display
sensor.set_vflip(True)

# Load Haar Cascade
# By default this will use all stages, lower satges is faster but less accurate.
face_cascade = image.HaarCascade("frontalface", stages=25)

# FPS clock
clock = time.clock()

while (True):
    clock.tick()

    # Capture snapshot
    img = sensor.snapshot()

    # Find objects.
    # Note: Lower scale factor scales-down the image more and detects smaller objects.
    # Higher threshold results in a higher detection rate, with more false positives.
    objects = img.find_features(face_cascade, threshold=0.5, scale=1.5)

    if objects:
        blink()
        say()

    # Draw objects
    for r in objects:
        img.draw_rectangle(r)
        print(r)

Note you can use sensor.set_vflip(True) to flip upside down, and image.width/height() to get frame dimensions.