I am writing a socket network application using android client and python server. The client side is almost perfect to send two values "1" and "2" . In the server side, the server will receive the value to check if the value equal to "1", the the motor servo will move from right to left or if the value equal to 2 the motor will move from left to right. Please look at the code:
# server.py
import socket
import RPi.GPIO as IO
import time
IO.setmode(IO.BOARD)
IO.setup(12,IO.OUT)
pwm2=IO.PWM(12,50)
# create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = "192.168.1.10"
# bind to the port
s.bind((host, 18050))
# queue up to 5 requests
s.listen(1)
while True:
print("Listenng to the client" )
# establish a connection
clientsocket,addr = s.accept()
print("Got a connection from %s" % str(addr))
d=int(clientsocket.recv(1024))
if d==1:
print(d, "right to left")
pwm2.start(12)
time.sleep(3)
pwm2.stop()
elif d==2:
print(d, "left to right")
pwm2.start(2)
time.sleep(3)
pwm2.stop()
IO.cleanup()
s.close()
In the implementation, a strange behavior always happen. Sometimes the motors will move while at other times they are not. Moreover, they will move only one time from right to left and left to right. The result is as follow:
>>
Listenng to the client
Got a connection from ('192.168.1.9', 1313)
(1, 'right to left') # Movement occurs
Listenng to the client
Got a connection from ('192.168.1.9', 1337)
(2, 'left to right') # Movement occurs
Listenng to the client
Got a connection from ('192.168.1.9', 1383)
(1, 'right to left') # No Movement occurs
Listenng to the client
Got a connection from ('192.168.1.9', 1416)
(2, 'left to right') # No Movement occurs
Listenng to the client
Got a connection from ('192.168.1.9', 1445)
(1, 'right to left') # No Movement occurs
Listenng to the client
Got a connection from ('192.168.1.9', 1528)
(2, 'left to right') # No Movement occurs
Listenng to the client
Got a connection from ('192.168.1.9', 1574)
(1, 'right to left') # No Movement occurs
Listenng to the client
Please any suggestion ?... The whole idea is to control the servo by sending 1 or 2 from android activity. Thank you in advance for any help you may lend.
3 suggestions :
You should not accept connection in the loop. You had better accepting only once and then working with this connection as long as you need it.
If you dont mind your servo to be on between two calls to your service, maybe you could avoid starting/stopping the PWM pin and just change the duty (function ChangeDutyCycle(xx))
If you can use the GPIO18 (pin 12) as it is hardware PWM. The software ones works well but they use DMA transfer to achieve this which can be resource consuming (I experienced some delay too)
Related
First time using Stack overflow so I'll do my best to explain.
TLDR - HOW DO I MAKE A PI PICO W CONNECT TO A NETWORK WITH WPS?
I'm making a thing, that basically checks whether the value of a particular stock has gone up or down and lights up green or red LED's based on whether the price is up or down. That's all well and good, but to do this it needs to connect to wifi, and being that the thing I'm making has no screen, or keyboard, all we have to accomplish this is the LED's (for the device to communicate with us) and whatever button I put on there.
My plan was to have the device look at a file called "your_wifi_details.txt" for the SSID and pass, and if it finds them, connect - if nothing is there, or if it cannot connect using those details, it is to enter "WPS mode" where the lights will flash, and the user presses the WPS button on their router then presses a button on the device.
Everything is wired up and working perfectly aside from I cannot work out how to get WPS to work on a Pi Pico W. I think I've gotten really close, but i'm getting the error "'CYW43' object has no attribute 'scan_wps'"
(The lines of code are:
# If the button is pressed, scan for WiFi networks that support WPS
if not button.value():
sta_if.scan_wps()
# Connect to the first WiFi network that supports WPS
sta_if.connect_wps()
)
Then it goes on to connect to the API's and such to get the stock price and from there everything is good.
Literally everything works, if I manually go into the "your_wifi_details.txt" and put in a correct SSID and password, we're golden, but I can't have users required to download thonny and connect to the device and edit files and yada yada... so I am really hoping this WPS thing can work.
This is the first 'proper' program i've written since starting to learn python so apologies if this is a stupid approach, it's taken a lot or time and confusion to get this far but it's so nearly working, I just need a little help over the finish line so if anyone has faced this problem or can help me toward a solution I'd be super grateful
Here's excerpts from the relevant bits of code that are connected to the problem. There's a lot of "print" debugging commands so I can see in the terminal in Thonny where the program is at and what it's doing, obviously in the final use case there won't be a screen or keyboard so all that stuff will be taken out once development is complete:
import urequests
import network
import time
import machine
#--------------(Stackoverflow comment) then further down
#stackoverflow comment: I don't know why this next line is in bold, it shouldn't be
# Set up the button (connected to pin 15)
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)
print ('pin 15 set as button')
#--------------(Stackoverflow comment) then further down still
while True:
print ('enter while true loop')
# Connect to the WiFi network
sta_if = network.WLAN(network.STA_IF)
#print ('firstline passed, sleeping for 10 seconds')
#ignore this, unnecessary now
#for i in range (0, 20):
# time.sleep(0.55)
# print ('sleeping...')
#print ('nap over, trying to continue..')
sta_if.active(True)
print ('firing up connection')
# Read the WiFi SSID and password from the text file
with open("your_wifi_details.txt", "r") as f:
ssid = f.readline().strip()
password = f.readline().strip()
print ('read your_wifi_details.txt successfully')
# Try to connect to the WiFi network
sta_if.connect(ssid, password)
print ('attempting to connect to wifi')
# Wait until the device is connected to the WiFi network
while not sta_if.isconnected():
# Flash the LEDs to indicate that the device is unable to connect
print ('connection failed, attempting to flash LEDs')
green_led.on()
red_led.on()
time.sleep(0.5)
green_led.off()
red_led.off()
time.sleep(0.5)
# Set up the button (connected to pin 0)
print ('setting up button for WPS')
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)
# If the button is pressed, scan for WiFi networks that support WPS
if not button.value():
sta_if.scan_wps()
# Connect to the first WiFi network that supports WPS
sta_if.connect_wps()
# Save the WiFi SSID and password to the "your_wifi_details.txt" file
with open("your_wifi_details.txt", "w") as f:
f.write(sta_if.config("essid") + "\n")
f.write(sta_if.config("password") + "\n")
print ('wifi details written to file')
# Print the WiFi connection status in the terminal so I can see if it worked
print("Connected to WiFi:", sta_if.isconnected())
I asked how to make TCP server that send data all the time in here: Julia TCP select and it works great. I now I have new problem, so I thought to start new conversation.
I did this kind of connection like on the picture:
So Sender sends sometimes something to server 1 and server 1 reads it and updates what to send to server 2 and Server 2 calculates numbers and communicates with C program.
Here is my server 1 code:
notwaiting = true
message = zeros(10,14)
server = listen(5001)
connection = connect(5003)
while true
if notwaiting
notwaiting = false
# Runs accept async (does not block the main thread)
#async begin
sock = accept(server)
reply= read(sock, Float64, 11)
message[:,convert(Int64,reply[1])] = reply[2:11]
write(connection,reshape(message,140))
global notwaiting = true
end
end
write(connection,reshape(message,140))
if message[1,1] == -1.0
close(connection)
close(server)
break
end
sleep(0.01) # slow down the loop
end
Sender is:
Connection2= connect(5001)
message = [2.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0]
write(Connection2,message)
close(Connection2)
And server 2 is like this:
function Server2_connection()
println("Waiting for connection")
server2 = listen(5003)
conn_2 = accept(server2)
while isopen(conn_2)
try
message_server2 = round(read(conn_2,Float64,140),3)
ins_matrix = reshape(message_server2[1:140],10,14)
catch e
println("caught an error $e")
break
end
end
println("Connection closed")
close(conn)
close(server)
end
The problem is that everything together is really heavy. I mean that I can send 2 messages from sender and everything is running really slow. I can run the whole thing 10-15s and then it freezes. All the connections work, but really slowly. My question is am I missing something or have something that makes the servers really slow? How can I code this better way?
I don't have anymore problem with slowness. I got help from julia-users google forum and on of them(Tanmay K. Mohapatra) wrote better code for same purpose: https://gist.github.com/tanmaykm/c2ab61a52cc5afa0e54fe61905a48ef1 It works
same way.
One problem with both codes is that they don't close connections properly. If server 2 goes down, the server 1 gets writing error and server 1 stays in listen mode.
Other ways it works. Thanks to Tanmay!
Edit: found the slower....the thing what should slow things down, did it. The sleep command did slow things down, but it slowed down more than I expected. If I had sleep variable 0.001 seconds, it will slow down the whole system like 0.014s. So I removed sleep command and it works fine.
I have two xbee's series 1. I have them as endpoint devices working in API mode and talking to each other. The first xbee is attached at a raspberry pi, while the other is on my pc where I see the terminal tab of XCTU program. The baud rate I use is 125000.
From raspberry pi I try to send a jpg image which is 30Kbytes. I send data frames 100 byte long (the biggest as it is said in the xbee documentation). Inside a loop I create and send the packets, I have also a cout statement that prints the loop number. Everything is fine and all bytes are sent. When I comment out the cout statement not all bytes are sent.
From what I have understood the cout statement works as a delay between packets, but I still cannot understand why is this happening as it is supposed that I use the half speed ...
I hope I was clear and look forward for a reply.
UPDATE
Just to summarize, i changed baud rate to 250000 where there is the same behavior as in 125000. I also implemented hardware flow control by checking cts signal. When xbees are in transparent mode I need a delay between sending characters at around 150us. The same goes for api mode too. The difference with 125000 baud rate in api mode was that the delay needed, was enough to be betwween each data packet, but in 250000 the delay is needed between each byte that i send. If i do the above everything goes well.
The next thing i did was to plug both xbees in my pc in transparent mode. I went to terminal tab of xctu software where i chose assemble packet and sent at around 3000 bytes to the other xbee. The result was the same. The second xbee received at about 1500 bytes and then each time that i was sending one byte from the first to the second, the "lost bytes" were being received at packets of 1000. :/
So could anyone know what am I doing wrong?
You should connect the /CTS pin from the XBee module into the Raspberry Pi, and have your routine stop sending data when the XBee de-asserts it.
At higher baud rates, it's possible to stream data into the XBee module faster than it can send to the remote module. The local XBee module uses the /CTS pin to notify the host when its buffers are almost full and the host should stop sending. People refer to this as hardware flow control.
It may be necessary to modify the serial driver on the Raspberry Pi to make use of that signal -- it should pause the transmit buffer when de-asserted, and automatically resume sending when re-asserted.
I have the following code:
...
namespace ba = boost::asio;
...
ba::ip::tcp::resolver resolver(ioService);
ba::ip::tcp::socket sock(ioService);
ba::ip::tcp::resolver::query query(the_ip, the_port);
ba::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
ba::ip::tcp::resolver::iterator end;
boost::system::error_code error = ba::error::host_not_found;
while (error && (endpoint_iterator != end))
{
sock.close();
sock.connect(*endpoint_iterator++, error);
}
When the server is up, it connects instantly and the rest of the code flows wonderfully, but when the server is offline or unreachable this while takes forever to exit.
Before the while: 09:04:37
When it exits: 09:05:40
Since I give query ONE IP and ONE PORT, shouldn't it exit instantly, given no connection can be established?
Are there any parameters I didn't configure? Something like "try X times" or "try for Y seconds"?
EDIT:
As seen in the comments, the problem seems to be a search on the internet, but the connection is local! (192.168...)
Why does it search the internet for a local IP?
As #MartinJames said on the comments:
"The internet is quite big, and has all sorts of links, some with very high latency.
Determining unreachability therefore takes a long time.
That is what happens when you connect all the computers on a planet together."
I tried disconnecting from the internet and the while exited instantly.
But the IP I'm using is local (192.168...), so this is still strange.
Thanks, man.
[Disclaimer: my knowledge of sockets is very rusty, and I'm just getting into R, so if I missed something completely obvious, please point it out!]
If I understand the (sparsely-documented) R functions for creating and managing sockets, namely socketConnection and make.socket, it appears that when creating a server socket (server=TRUE), the moral equivalent of the following is carried out:
s = socket(yada yada);
listen(s, ...);
s2 = accept(s, ...);
close(s, ...);
and now I can work with s2 but can't loop to deal with a backlog of incoming connections to s. Is this more-or-less right? Is there any way to keep listening and continue to deal with additional incoming connections after handling the first?
I'd like to know the answer to this one too! ...but in the meantime I can at least suggest a work-around with some limitations:
If you can know HOW MANY clients will connect, then the following should work.
On the server:
n=2 # Number of clients
port=22131
slist=vector('list',n)
# Connect to all clients
for(i in 1:n) slist[i] <- socketConnection('localhost', port=port, server=TRUE)
# Wait for a client to send data, returns the client index
repeat {
avail <- which( socketSelect(slist) )[[1]]
# ...then read and process data, rinse, repeat...
}
On each client:
port=22131
# Connect to server
s <- socketConnection('localhost', port=port)
# ...then send data...
writeLines(c('foo', 'bar'), s)
No, you can touch the back-log on s1.
Window 1:
$ R
s1 = socketConnection(server=T,port=12345)
s2 = socketConnection(server=T, port=98765)
Window 2:
$ nc localhost 12345
If ever I should leave you, it wouldn't be in springtime
Knowing how in spring I'm bewitched by you so
oh no not in springtime, summer, winter, or fall
no never could I leave you at all
Window 3:
$ nc localhost 98765
for Hitler and Germany
Deutschland is happy and gay
we're marching to a faster pace
look out, here comes the Master Race!
Window 1:
readLines(s1,1)
# "if ever I should leave you, it wouldn't be in springtime"
readLines(s2,1)
# "for Hitler and Germany"
readLines(s1,1)
# "knowing how in spring I'm bewitched by you so"