Free Domestic Shipping on Orders Over $100!

Blink-Ping: A WiPy LED blink with a simple TCP socket

by Ed Bennett September 09, 2016

Blink-Ping: A WiPy LED blink with a simple TCP socket

The Blinky_Ping_client.py script shows an unusual way to blink an LED and test a simple TCP socket script. The video has sound, but the volume is low. 


The WiPy is first of all a wireless device, and resolutely so. It wasn’t for a couple of minutes after finishing the WiPy’s unboxing  and blinky test (super easy) that I realized the USB cable to my laptop had contributed nothing but power for the WiPy. No data went over the cable. It was all about wireless internet from the first moment. Blinking an LED tells you things are alive and working. Pinging a server tells you that somebody's home and a bit about the speed of the network connection. Listening to the sound of connections being opened and closed give you a very different experience of how the system is behaving.

The WiPy connection overview

[click View Image for more detail] Blinky_Ping also makes sound. The speaker is from an old phone handset. Most speakers are around 8 ohms impdance. This one is 165 ohms because it's from a phone. 165 ohms is printed on the back of the speaker. The higher impedance is what allows an un-amplified connection to a 3.3V logic line.  The sound output is a small number of milliwatts.
The floating wire goes to GP10. Touching it to 3.3V signals the WiPy to exit its while loop. 

Clients and servers are pieces of software. Servers sit and wait for a client request. The basic blinky of socket programming is to make a connection between a client socket and a server socket, then then do something like print Hello World on both ends of the connection to see that it’s alive, then close the connection. The Blinky_Ping_client.py script (WiPy) does a sort of ping by opening and closing a socket on Blinky_Ping_server.py (laptop). The "ping" time can be seen in how fast the LED blinks. Each time a socket is opened and closed the LED turns on and then off once. Each time the LED turns on or off, the speaker emits a click. The clicks bracket the time spent opening, then interacting, then closing the socket. In my case theinterval ranged from 7ms to 2500ms.

A 74HC573 chip buffers the WiPy up to around 20mA at 3.3V. The narrow black thing is the pull down for the '573 inputs. It's an R-pak resistor network that has eight 10k resistors tied to a common ground. Very compact. Only one of the eight channels is being used. The speaker and the LED share the same channel.

In socket programming, "socket" is an electrical metaphor that represents an IP address and a port number taken together. Sockets are created by applications that want to communicate with other applications.

The speaker capacitor

The green and orange jumpers are the speaker leads. The ground side of the speaker passes through a 1uF capacitor. Any value between 1uF and 250uF work fine. Watch for polarity on electrolytic caps!

By ancient custom some port numbers are associated with particular well known services or protocols. Port 80 is used by web servers. A web server socket looks like “192.168.1.1:80”. There are about 65000 possible port numbers. Port numbers are chosen by the program or handed out by the operating system. Port numbers must match expectations on both ends of the connection so that the client and server can find each other.

server and client termnal windows

The client repl is on the left. The server is on the right. The server is a Python script running on the laptop.

To make your own network software, you write either a server program or a client program or both. The server and client can talk to each other because bytes have the same meaning on both ends of the connection. The point is that you can make up your own scheme to describe your data and the method for passing it over a network connection. That is to say you can make up your own protocol. Python has extensive libraries for writing your own clients and servers.

serial terminal

The telnet session and the serial terminal show the same information, but the Cutecom serial terminal is easier to read than the telnet window, IMO. The serial connection often still works if the wireless connection fails.

In small embedded systems, we're used to seeing the server code running on the small device and the client, e.g. a web browser running on the laptop. Not so here. In this case, the WiPy is the client. Servers must listen at all times for a client request, and so must stay awake, thus draining their battery. If the embedded device is the client, it can wake up from hibernate whenever it pleases, then interact with the server, then go back to sleep. Blinky_Ping doesn't use a low-power configuration, but low power is the way of the future.

 

Here is the client:

# Blinky_Ping_client.py, alias main.py on wipy
# Ed Bennett

'''
This was helpful:
http://www.bogotobogo.com/python/python_network_programming_server_client.php

This script does a sort of ping by measuring the time of opening and 
closing a socket on a remote server. (Blinky_Ping_server.py) The "ping" 
time can be seen in how fast the LED blinks. When a socket is starting 
to be opened the LED turns on. When the socket has closed the LED turns 
off.
'''

if __name__ == '__main__':

    import socket
    import time
    from machine import Pin

    host = '192.168.1.64' # laptop running server
    port = 9999
    addr = socket.getaddrinfo(host, port)[0][-1]
        
    # The expansion board is designed so that the"user led" on G16 
    # is switched on the low side [google for low-side switch],
    # therefore the LED's logic level is inverted. 1 is off, 0 is on. 
    # The GP16 pin itself is NOT inverted.
    LED1 = Pin('GP16', mode=Pin.OUT)
    
    LED1.value(1) # blink once to check wiring on startup
    time.sleep_ms(1000)
    LED1.value(0)
    time.sleep_ms(1000)
    
    w = 0 # while loop counter
    elapsed = 10 # initialize to 10ms
'''
The stop_flag allows you to stop a broken, long, or infinite loop and 
interact with the filesystem by using commands in the os module, etc.   
Making GP10 high (touch a jumper between GP10 and +3.3V) causes the 
while loop to end and return you to the repl.
'''
    stop_pin = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN) 
    stop_flag = 0  
    stop_flag = stop_pin() # check here in case the while loop is broken      
    while w < 1000 and stop_flag == 0:
        stop_flag = stop_pin()
        print("stop_flag = ", stop_flag)
        if stop_flag == 1:
            print("stopped")
            break
'''
This pauses the loop for the same number of milliseconds as the previous
message's round-trip. Otherwise it would be hard to see the LED blinking.
The measured value of "elapsed" is not affected.                     
'''
        time.sleep_ms(elapsed)

'''
Measure the overhead in sending data between my laptop and the WiPy 
through my home router: start a timer, then connect to the server, then 
don't send any data, then receive some data from the server, then close 
the socket, then stop the timer. 
''' 
        LED1.value(1)
        start = time.ticks_ms() # init the elapsed timer: start measuring

        # create a socket object
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        s.connect(addr)

        # This just shows the idea of a small amount of data coming
        # back from the server.
        # Receive no more than 1024 bytes
        tm = s.recv(1024)                                     
    
        s.close()            
        elapsed = time.ticks_diff(start, time.ticks_ms()) #measure loop time
        LED1.value(0)        
       
        print("Loop #", w, " round trip time was", elapsed, "ms")
        print("The time got from the server is %s" % tm.decode('ascii'))
            
        w += 1

 

Here is the server:

# Blinky_Ping_server.py 
# runs on laptop
# http://www.bogotobogo.com/python/python_network_programming_server_client.php
# This is pretty much the standard minimal server socket demo, but with the 
# added feature of sending the time to the client.

import socket                                         
import time

# create a socket object
mytcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mytcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#
# get this computer's name 
# host = socket.gethostname() this was getting machine name not ipaddr
                          
host='192.168.1.64' # only the server's actual ip address works here (?!) 
port = 9999                              

# bind to the port
mytcpsock.bind((host, port))                                  

# queue up to 5 requests
mytcpsock.listen(5)                                           

while True:

    # establish a connection
    clientsocket,addr = mytcpsock.accept() 

    print("Got a connection from %s" % str(addr))

    currentTime = time.ctime(time.time()) + "\r\n"
    clientsocket.send(currentTime.encode('ascii'))
    clientsocket.close()

Ed Bennett ed atsign kineticsandelectronics dotcom
 





Ed Bennett
Ed Bennett

Author


Leave a comment

Comments will be approved before showing up.


Also in News

Our new location

by Craig L August 10, 2017

Continue Reading

VM-CLAP1 👏 sensor + gpiozero on Raspberry Pi

by Stewart Russell June 19, 2017

Continue Reading

Lower International Shipping Rates!

by Craig L June 14, 2017

Continue Reading