I'm using a Adafruit Ethernet FeatherWing plugged into an Adafruit Feather 328P and I want to send and receive UDP packets from a Python application. I'm using the stock Arduino UDP code just to see what I'm sending. Here's my Python code:
def write_Arduino(self):
sock_readresp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_readresp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock_readresp.bind((self.config["DEFAULT"]["THIS_IP_ADDRESS"], int(self.config["DEFAULT"]["RECEIVE_PORT"] )))
sock_readresp.settimeout(.2)
MESSAGE = struct.pack("30c", b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9',
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9',
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9')
print("Message is {}".format(MESSAGE))
sock_read = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock_read.setblocking(0)
sock_read.bind((self.config["DEFAULT"]["THIS_IP_ADDRESS"], 0))
sock_read.sendto(MESSAGE,(self.config["DEFAULT"]["ARDUINO_IP_ADDRESS"],int(self.config["DEFAULT"]["SEND_PORT"])))
sock_read.close()
My settings are:
THIS_IP_ADDRESS = 192.168.121.1
ARDUINO_IP_ADDRESS = 192.168.121.2
SEND_PORT = 8888
RECEIVE_PORT = 32001
and I've updated the Arduino code to reflect that. When I send this packet, I can confirm it through Wireshark on my PC
I seem to be sending exactly what I think I am. A string of "012345678901234567890123456789" (Wireshark shows the ASCII characters in hex, as seen here). However, receiving it on the Arduino looks like this:
Received packet of size 30
From 192.168.121.1, port 64143
Contents:
012345678901234567890123D6789
The 25th and 26th byte always show up like that, and I'm missing the actual data. What could be going on here?
Related
I'm trying to get the data stream of a sensor transmitter that uses the modbus rtu communication protocol on my raspberry pi 3B. I'm able to get the data with the pymodbus2.5.3 library.
For this I use this code:
from pymodbus.client.sync import ModbusSerialClient # Import the pymodbus library part for syncronous master (=client)
client = ModbusSerialClient(
method='rtu', #Modbus Modus = RTU = via USB & RS485
port='/dev/ttyUSB0', #Connected over ttyUSB0, not AMA0
baudrate=19200, #Baudrate was changed from 38400 to 19200
timeout=3, #
parity='N', #Parity = None
stopbits=2, #Bites was changed from 1 to 2
bytesize=8 #
)
if client.connect(): # Trying to connect to Modbus Server/Slave
#Reading from a holding register
res = client.read_holding_registers(address=100, count=8, unit=1) #Startregister = 100, Registers to be read = 8, Answer size = 1 byte
if not res.isError(): #If Registers don't show Error
print(res.registers) #Print content of registers
else:
print(res) #Print Error Message, for meaning look at (insert git hub)
else: #If not able to connect, do this
print('Cannot connect to the Transmitter M80 SM and Sensor InPro 5000i.')
print('Please check the following things:')
print('Does the RS485-to-USB Adapter have power? Which LEDs are active?')
print('Are the cables connected correctly?')
And get the following output:
[15872, 17996, 16828, 15728, 16283, 45436, 16355, 63231]
With the help of the Modbus Poll and Slave Programms I know that those results should decoded be:
[0.125268, --, 23.53, --, 1.21094, --, 1.77344, --]
To get to the right results I tried the command that the pymodbus github suggests .decode():
res.decode(word_order = little, byte_order = little, formatters = float64)
[I know that those aren't the needed options but I copied the suggested github code to check if it works.]
After putting the code segment into the code the changed part looks like this:
if not res.isError(): #If Registers don't show Error
res.decode(word_order = little, byte_order = little, formatters = float64)
print(res.registers) #Print content of registers
else:
print(res) #Print Error Message, for meaning look at (insert git hub)
When I run this code, I get the following output, that traces to the decoding segment:
NameError: name 'little' is not defined
After this, I imported also the pymodbus part translation. But it showed the same output.
How can I decode my incoming data?
You can use BinaryPayloadDecoder to help decoding your payload, here is a simplified example, change Endian.Big and Endian.Little if needed.
if client.connect(): # Trying to connect to Modbus Server/Slave
#Reading from a holding register
res = client.read_holding_registers(address=100, count=8, unit=1) #Startregister = 100, Registers to be read = 8, Answer size = 1 byte
# ====== added code start ======
decoder = BinaryPayloadDecoder.fromRegisters(res.registers, Endian.Little, wordorder=Endian.Little)
first_reading = decoder.decode_32bit_float()
second_reading = decoder.decode_32bit_float()
# ====== added code end ======
if not res.isError(): #If Registers don't show Error
print(res.registers) #Print content of registers
else:
print(res) #Print Error Message, for meaning look at (insert git hub)
Remember to import from pymodbus.payload import BinaryPayloadDecoder at top and add necessary exception handlers in your final code.
Reference document: https://pymodbus.readthedocs.io/en/latest/source/library/pymodbus.html#pymodbus.payload.BinaryPayloadDecoder
I am developing a program to read Modbus data via serial RTU using pymodbus.
My purpose is to read data from an ABB XRCG4 Xseries flow computing PC. I know that the COM port on the device side is COM1 and the serial protocol is RS232, on my PC, using a serial converter I am trying to connect to it.
I know the configuration as follows:
PROTOCOL= 'rtu'
USB_PORT = 'COM4'
PARITY = 'None'
BAUD_RATE = 9600
TIMEOUT = 3
For test purposes I made an Arduino board into a Modbus Slave. I can read the data from the board with QModMaster, Modbus Pool and SimplyModbusMaster but I am unable to do so with my script. For the board I am unable to read anything at all, not eve with the programs mentioned above.
When I use the above mentioneds program to read data from the Arduino, everything works fine, when I try with my script, I get the AttributeError: 'ModbusIOException' object has no attribute 'registers'
I also noticed that I get this error if I unplug the cable while connection is running.
What am I missing? My guess is that I might not have a hardware dealer for the dsrdtr exchange, according to page 24 of the pymodbus documentation or maybe on the board side, the Register Format is not ok for my code.
Here you can see the details from the ABB board
Port description part1
Port description part2
My code:
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.client.sync import *
from pymodbus.register_read_message import *
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.compat import iteritems
from pymodbus.exceptions import *
import time
import logging
import logging.handlers as Handlers
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)
USB_PORT = 'COM4'
PARITY = 'N' #'N'
BAUD_RATE = 9600
TIMEOUT = 0.15
client = ModbusClient(method='rtu',
port=USB_PORT,
stopbits=1,
bytesize=8,
parity=PARITY,
baudrate=BAUD_RATE,
timeout=TIMEOUT, )
while True:
connection = client.connect()
#print(client.)
print(f"COM Details {client.socket}")
#client.socket.setRTS(True)
print(f"Connection status is: {connection} \nClient State: {client.state} \nTimeout: {client.timeout}")
#print(client.get_serial_settings)
try:
#################################### CITIM INPUT REGISTER (adresa,nr de registrii si unit ID
input_value = client.read_input_registers(count=0x01,address=10,unit=0x01)
#client.socket.setRTS(False)
print(input_value)
decoder = BinaryPayloadDecoder.fromRegisters(input_value.registers, byteorder=Endian.Little)
decoded = {
'string': decoder.decode_string(8),
'float': decoder.decode_32bit_float(),
'16uint': decoder.decode_16bit_uint(),
'ignored': decoder.skip_bytes(2),
#'8int': decoder.decode_8bit_int(),
'bits': decoder.decode_bits(),}
############### CITIM HOLDING REGISTER (exemplu, modelul vantilatorului)
holding_values = client.read_holding_registers(0xD1A5,6,unit=0x01)
holding_decoder = BinaryPayloadDecoder.fromRegisters(holding_values.registers, byteorder=Endian.Big)
holding_decoded = {
'string': holding_decoder.decode_string(8),
#'float': holding_decoder.decode_32bit_float(),
#'16uint': holding_decoder.decode_16bit_uint(),
'ignored': holding_decoder.skip_bytes(2),
#'8int': holding_decoder.decode_8bit_int(),
'bits': holding_decoder.decode_bits(),
}
print("-" * 60)
print("INPUT REGISTERS:")
print("-" * 60)
print(f"\nResponse: {input_value.registers} \nInput Registers Decoded values: \n")
for name, value in iteritems(decoded):
print ("%s\t" % name, value)
print(f"\n Decoded speed: {decoded['float']}")
print(f"Holding values registers:\n {holding_values.registers}")
print("-" * 60)
print("Holding Values Decoded Data")
print("-" * 60)
for name, value in iteritems(holding_decoded):
print ("%s\t" % name, value)
except ConnectionException as e:
print(f"USB Disconnected {e}")
time.sleep(2)
client.close()
I'm trying to write a fake access point script in ruby; the script is below:
require 'packetgen'
def fake_ap
print 'Making a fake ap...'
while true
bssid = 'aa:aa:aa:aa:aa:aa'
iface = 'mon0'
ssid = 'NoWifi'
broadcast = 'ff:ff:ff:ff:ff:ff'
pkt = PacketGen.gen('RadioTap')
pkt.add('Dot11::Management', mac1: broadcast, mac2: bssid, mac3: bssid)
pkt.add('Dot11::Beacon', cap: '0x1114')
pkt.dot11_beacon.add_element(type: 'SSID', value: ssid)
pkt.dot11_beacon.add_element(type: 'Rates', value: "\x82\x84\x8b\x96\x24\x30\x48\x6c")
pkt.dot11_beacon.add_element(type: 'DSset', value: "\x06")
pkt.dot11_beacon.add_element(type: 'TIM', value: "\x00\x01 \0x00\0x00")
pkt.calc
pkt.to_w(iface)
end
end
fake_ap
Hexdump of packet
The program is supposed to send beacon frames; I ran the program (with my wireless card on monitor mode) however it doesn't show up as an access point. It there a problem with my code or something else. The docs for the packetgen library are here. Thanks!
I have problem with reading data from my Arduino.
Here is what I send from my arduino to Pycharm:
Serial.println("ArduinoMega");
and here is my code with Pycharm which reads and compares to b'ArduinoMega':
ser = serial.Serial(port,baudrate=9600, timeout=1)
ser.write(b'\x00')
print(port)
serial.time.sleep(2)
rec = (ser.readline(len(b'ArduinoMega')))
print(rec)
if rec == b'ArduinoMega':
ser.close()
return port
ser.close()
By default, pyserial sets dtr pin high when opening new connection. Arduino boards are made to reset themselves when connected to with high dtr, so your Arduino resets when you open connection with your computer and does not initialize its serial port in time when you send your package and expect reply.
To solve this programmatically, you can change your code to:
ser = serial.Serial()
ser.port = port
ser.baudrate = 9600
ser.timeout = 1
ser.dtr = False
ser.open()
ser.write(b'\x00')
rec = ser.read(len(b'ArduinoMega')
if rec == b'ArduinoMega':
ser.close()
return port
ser.close()
Also, note change in ser.read... line.
I am trying to send AT commands to ESP8266 to get connected with internet with the Wifi.
When I am sending AT and AT+RST command on serial monitor then I am getting OK and ready response which seems perfect.
Then I am sending AT+CWLAP to get list of available wifi networks which is also executing correctly.
AT+CWLAP
+CWLAP:(3,"Moto",-42,"a4:70:d6:7a:fa:6c",1,25,0)
+CWLAP:(4,"PRANJAL",-95,"1c:a5:32:3d:f5:c4",1,-16,0)
+CWLAP:(2,"VIHAN",-94,"c8:3a:35:2f:1d:81",1,-21,0)
+CWLAP:(3,"Tenda",-93,"c8:3a:35:20:a9:b1",9,-4,0)
OK
Then I sent AT+CWMODE? which is also perfect.
AT+CWMODE?
+CWMODE:1
OK
Now I am trying to connect ESP8266 with above listed Wifi with this command, it is sending an ERROR on serial monitor.
AT+CWJAP_DEF="Moto","reset1234"
Error
⸮=IRe"Moto","reset1234"
ERROR
Can anyone suggest me what could be the reason of this issue ?
#include "SoftwareSerial.h"
SoftwareSerial esp8266(2, 3); // RX, TX
void setup()
{
Serial.begin(9600); // serial port used for debugging
esp8266.begin(9600); // your ESP's baud rate might be different
}
void loop()
{
if(esp8266.available()) // check if the ESP is sending a message
{
while(esp8266.available())
{
char c = esp8266.read(); // read the next character.
Serial.write(c); // writes data to the serial monitor
}
}
if(Serial.available())
{
delay(10); // wait to let all the input command in the serial buffer
// read the input command in a string
String cmd = "";
while(Serial.available())
{
cmd += (char)Serial.read();
}
// send to the esp8266
esp8266.println(cmd);
}
}
The current official AT command set seems to be documented on https://github.com/espressif/ESP8266_AT/wiki/AT_Description
http://espressif.com/sites/default/files/documentation/4a-esp8266_at_instruction_set_en.pdf
https://www.itead.cc/wiki/ESP8266_Serial_WIFI_Module#AT_Commands
If the module is to be configured as a client, i.e. to connect to an access point, the following AT commands have to be sent (11500 baud 8N1, CR-LF line termination):
AT+RST
AT+CWMODE=3 (1 is "Station" only (wifi client), 3 is mixed mode "Station and Access-Point", both should work)
AT+CWJAP="Moto","reset1234"
AT+CWJAP_CUR="Moto","reset1234" (temporary) or
AT+CWJAP_DEF="Moto","reset1234" (stored)
For reference, a "success story" (ESP8266 module with USB-UART, Software: HTerm, Access Point with WPA2 (both TKIP / CCMP tested)):
AT<\r><\r><\n><\r><\n>
OK<\r><\n>
AT+RST<\r><\r><\n><\r><\n>
OK<\r><\n>
<\r><\n>
ets Jan 8 2013,rst cause:2, boot mode:(3,6)<\r><\n>
<\r><\n>
load 0x40100000, len 1856, room 16 <\r><\n>
tail 0<\r><\n>
chksum 0x63<\r><\n>
load 0x3ffe8000, len 776, room 8 <\r><\n>
tail 0<\r><\n>
chksum 0x02<\r><\n>
load 0x3ffe8310, len 552, room 8 <\r><\n>
tail 0<\r><\n>
chksum 0x79<\r><\n>
csum 0x79<\r><\n>
<\r><\n>
2nd boot version : 1.5<\r><\n>
SPI Speed : 40MHz<\r><\n>
SPI Mode : DIO<\r><\n>
SPI Flash Size & Map: 32Mbit(512KB+512KB)<\r><\n>
jump to run user1 # 1000<\r><\n>
<\r><\n>
??r?d?l<18>?<31><\0><\f>?l`<3>??s?l?<28>?<19>?<4><4><4>$ <2>??r?$<4>??<27>?<4><4>ll`<3>r$?<18>?"<\0>????"<4>l?cs|<\f>?`?22???<27>BB<18>c??o??<18>NN?<16><2><\0><2>d$??<2>d??<\0>?<4>d??<\0>ll????d??l`<2>?<2>N?<\0>????"<4>d??<28>p<4><4><2><2>???"b<4>$<4>?"prlrl<\r><\n>
Ai-Thinker Technology Co. Ltd.<\r><\n>
<\r><\n>
ready<\r><\n>
WIFI DISCONNECT<\r><\n>
AT+CWMODE?<\r><\r><\n>+CWMODE:3<\r><\n>
<\r><\n>
OK<\r><\n>
AT+CWJAP_CUR="Moto","reset1234"<\r><\r><\n>
WIFI CONNECTED<\r><\n>
WIFI GOT IP<\r><\n>
<\r><\n>
OK<\r><\n>
AT+CIFSR<\r><\r><\n>+CIFSR:APIP,"0.0.0.0"<\r><\n>
+CIFSR:APMAC,"00:00:00:00:00:00"<\r><\n>
+CIFSR:STAIP,"0.0.0.0"<\r><\n>
+CIFSR:STAMAC,"00:00:00:00:00:00"<\r><\n>
<\r><\n>
OK<\r><\n>
AT+GMR<\r><\r><\n>AT version:1.1.0.0(May 11 2016 18:09:56)<\r><\n>
SDK version:1.5.4(baaeaebb)<\r><\n>
Ai-Thinker Technology Co. Ltd.<\r><\n>
Jun 13 2016 11:29:20<\r><\n>
OK<\r><\n>
This also works with mode=1.
Major rewrite.
Questions and ideas to test:
what is your module firmware version?
access point issues (e.g. MAC address restrictions)?
power supply good?
might there be any old configuration or other code running on the module?
what is the byte code of ⸮ in the error message - Is it two bytes 0x2E2E?
are you using the Arduino serial monitor for communication?
in contrast to my comment, maybe the arduino does have an influence (timing?). Try to rule this out by
doing the pass-through character-based instead of line-based, e.g.:
(end of list, no code possible otherwise:)
loop(){
if( esp8266.available() )
Serial.write(esp8266.read());
if( Serial.available() )
esp8266.write(Serial.read());
}
keeping the AVR in reset and connecting the ESP8266 serial lines directly to the USB-UART converter
Alright! I just tried to connect with different wifi and it got connected with it. It was some kinda issue with mobile hotspot.