Cant connect to Azure IoT Hub with Arduino Nano RP2040 Connect - mqtt

I have followed multiple tutorials and I am not stuck on this error.
256.705: INFO - - iot_mqtt :: connect :: redacted123.azure-devices.net
256.711: DEBUG - - iot_mqtt :: _on_connect :: username = redacted123.azure-devices.net/MyArduinoConnect/?api-version=2019-10-01, password = SharedAccessSignature sr=myiothub.azure-devices.net%2Fdevices%2Fredacted123ArduinoConnect&sig=OKeIy1cgk%2FQ9ok%2BiO359CWEBWDH1erL1lzQiZP7rwbk%3D&se=1637119964
256.719: DEBUG - Attempting to establish MQTT connection...
256.725: INFO - Establishing a SECURE SSL connection to redacted123iothub.azure-devices.net:8883
Connection error, reconnecting
Timed out waiting for SPI char
I have this firmware: adafruit-circuitpython-arduino_nano_rp2040_connect-sv-7.0.0
I have these libs: adafruit-circuitpython-bundle-7.x-mpy-20211116
And I'm using this code, which is as small as I can make it to reproduce.
import time
import board
import busio
from digitalio import DigitalInOut
import adafruit_requests as requests
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
# azure imports
from adafruit_azureiot import IoTHubDevice # pylint: disable=wrong-import-position
from adafruit_ntp import NTP
from secrets import secrets
# ESP32 pins
esp32_cs = DigitalInOut(board.CS1)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
# uses the secondary SPI connected through the ESP32
spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
print("Connecting to WiFi.")
requests.set_socket(socket, esp)
esp.connect_AP(secrets["ssid"], secrets["password"])
print("Connected: ", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi)
print("IP: ", esp.pretty_ip(esp.ip_address))
ntp = NTP(esp)
# Wait for a valid time to be received
while not ntp.valid_time:
print("waiting for NTP Time")
time.sleep(5)
ntp.set_time()
print("Wifi connected.")
device = IoTHubDevice(socket, esp, secrets["azure_device_connection_string"])
attempts = 0
while not device.is_connected() and attempts < 3:
attempts = attempts + 1
print("Connecting to Azure: #" + str(attempts));
try:
print("begin")
device.connect()
print("SUCCESSS!")
except BaseException as e:
print("Connection error, reconnecting\n", str(e))
time.sleep(2)
# need to reset this or self.device.is_connected() will explode on loop.
device = IoTHubDevice(socket, esp, secrets["azure_device_connection_string"])
if(attempts>=3):
print("failed to reach the cloud.")
time.sleep(60) # sleep for a minute before loops start over.
else:
print("Connected to cloud")
I never manage to connect to the Azure IoT Hub. Always the same SPI Error.
The error comes from this line:
device.connect()
Id appreciate any help, keep in mind I'm very new to Arduino, CircuitPython and IoT.

The solution was to upgrade the Nina Wifi firmware as explained here:
https://docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-upgrading-nina-firmware

Related

Wifi with ESP 8266 or 32

I need your help because I don't understand what's going on. I have 2 esp8266 , one in AP mode and the second in station mode.
When I connect the ESP in station mode to my box, it's ok.
On the other hand when I use this code to connect to the other ESP in AP mode with a fixed IP, the ESP remains in the while loop
import network
from time import sleep
def config_wifi():
ip = '192.168.144.3'
subnet = '255.255.255.0'
gateway = '192.168.144.1'
dns = '8.8.8.8'
ssid = 'MicroPython-AP'
password = '123456789'
ap=network.WLAN(network.AP_IF)
ap.active(False)
ap.disconnect()
print(ap.status()) # return None
sleep(2)
sta=network.WLAN(network.STA_IF)
sta.active(True)
sta.disconnect() # for ESP8266
sta.connect(ssid,password)
print(sta.status())# return 1001 : CONNEXION
sleep(2)
while (sta.isconnected()==False):
print(sta.isconnected())
sta.ifconfig((ip,subnet,gateway,dns))
ip=sta.ifconfig()[0]
print('Connected',ip)
return ip
def run():
config_wifi()
run()
Following my tests, I used an ESP32 Lolin with this program and I have the same result, ie False in the while loop.
The first status gives me None and the second 1001. Searching on different forums, 1001 means Connexion.
Status indicates that there is connection, on the other hand the while loop gives False
I do not understand Do you have an idea?

How to deal with "OSError: Available Interfaces are down" error message?

I am currently working with a Pycom device and try to connect it to an IoT platform (more precisely, Adafruit IO). I would like to make the platform and my device communicate. It used to work perfectly good, I could publish and subscribe using MQTT to topics/widgets configured on the website but lately, I have been given this error message when trying to connect to Adafruit with this protocol : OSError: Available Interfaces are down. I do not know why all of a sudden, this happens and I have no idea how to deal with. Sometimes, after a while or after numerous attempts, it works again but I would like to know more precisely what this is due to.
import umqtt
from umqtt import MQTTClient
import ubinascii
import micropython
import time
import machine
import pycom
pycom.heartbeat(False)
IO_SERVER = "io.adafruit.com"
AIO_SERVER = "io.adafruit.com"
AIO_PORT = 1883
AIO_USER = "user"
AIO_KEY = "key"
AIO_CLIENT_ID = ubinascii.hexlify(machine.unique_id()) # Can be anything
client = MQTTClient(AIO_CLIENT_ID, AIO_SERVER, AIO_PORT, AIO_USER, AIO_KEY)
import network
from network import WLAN
wlan=WLAN(mode=WLAN.STA)
pw='pw'
nets=wlan.scan()
for net in nets:
if net.ssid == 'myssid':
wlan.connect(net.ssid,auth=(None,pw),timeout=5000)
if wlan.isconnected() == True:
pycom.rgbled(0x007f00)
else:
pycom.rgbled(0x7f0000)
client.connect()
pycom.rgbled(0x7f7f00)
I used the umqtt module located here: https://github.com/micropython/micropython-lib/blob/master/umqtt.simple/umqtt/simple.py. I can connect to my wifi with no problem, the error happens at client.connect().
I had faced similar issue, what I realised is that there is some time required for the client to connect.
Add 2 sec delay before connect & like 10 secs

Trying to control fans on a raspberry pi 3 GPIO over Bluetooth Low Energey

I have 2 dual-h bridge controllers(used to supple power to fans) that are connected to my raspberry pi 3 b via GPIO and a battery for power I have created a script in python 3 that uses Bluetooth classic to ask the connected phone in a terminal how long the fan should be on for and how long they should be off for in a loop I have got this to work GREAT, but this works only on android as it is Bluetooth classic i now want to make this work for my iPhone as well i found out i would need to use BLE so my question is how can i convert my original script in Bluetooth classic(using RF COMM Sockets) to use Bluetooth Low Energy.
Here is my original script
# Importing the Bluetooth Socket library
import bluetooth
# Importing the GPIO library to use the GPIO pins of Raspberry pi
import RPi.GPIO as GPIO
import time
fan_pin = 16# Initializing pin 16 for fan
fan2_pin = 18
GPIO.setmode(GPIO.BOARD) # Using BCM numbering
GPIO.setup(fan_pin, GPIO.OUT) # Declaring the pin 16 as output pin
GPIO.setup(fan2_pin, GPIO.OUT) # Declaring the pin 16 as output pin
host = ""
port = 1 # Raspberry Pi uses port 1 for Bluetooth Communication
# Creaitng Socket Bluetooth RFCOMM communication
server = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
print('Bluetooth Socket Created')
try:
server.bind((host, port))
print("Bluetooth Binding Completed")
except:
print("Bluetooth Binding Failed")
server.listen(1) # One connection at a time
# Server accepts the clients request and assigns a mac address.
client, address = server.accept()
print("Connected To", address)
print("Client:", client)
while 1:
# Receivng the data.
client.send("How long do you want the fans to be on for?/n")
On = int(client.recv(1024)) # 1024 is the buffer size.
time.sleep(5)
client.send("Ok, Now how long do you want the fans to be off for?/n")
Off = int(client.recv(1024))
print(On)
print(Off)
while True:
GPIO.output(fan_pin, GPIO.HIGH)
GPIO.output(fan2_pin, GPIO.HIGH)
time.sleep(On)
GPIO.output(fan_pin, GPIO.LOW)
GPIO.output(fan2_pin, GPIO.LOW)
time.sleep(Off)
# Making all the output pins LOW
GPIO.cleanup()
# Closing the client and server connection
client.close()
server.close()
I would imagine this would be as simple as changing anything that was Bluetooth classic code to BLE code. Max like 20 lines to change?

UART data error when using uart.alt(1)

I am trying to acquire rs232 data from a device connected to the ESP8266 (data will then be sent our via http/wifi).
I am using max3232 IC to provide the necessary 3.3v TTL to the ESP8266.
I have have connected the max3232 (pin 12) to GPIO pin 13 (rx) on the ESP8266 (I am only receiving data not sending data, so only the rx pin is connected).
The code i am using:
--
--file: test2.lua
--
tst2 = require "tst2"
tst2.start()
--tst2.lua (testing script)
local module = {}
function module.start()
print("in tst2.start")
uart.alt(1) --use alt GPIO pin 13 (Rx)
uart.setup(0, 9600,8, uart.PARITY_NONE, uart.STOPBITS_1,0)
uart.on("data",10,
function(data)
file.open("data.tmp", "w+")
file.writeline("starting")
for i=1,10 do
file.writeline(string.byte(string.sub(data,i,i)) )
end
file.writeline("from uart: ", data)
file.writeline("finished")
file.close()
end, 0)
uart.alt(0) --switch back to standard Rx/Tx pins
end
return module
The rs232 device connected to the ESP8266 is putting out a single alphabetic character every 3 seconds, however the data written to file (data.tmp) is as follows
starting
10
13
10
13
10
13
10
13
10
13
from uart:
finished
file.close()
Problems:
1- The rs232 device is not issuing any newln or cr characters, but these are appearing in the data file.
2- the string "file.close()" is being written to the data file, and looks like it is the actual lua command that follows the final file.writeline command.
3- the alphabetic data is not appearing in the data file.
4- switching back to the standard uart pins via uart.alt(0) does not work (the ESP8266 must be rebooted - this is not a major issue as the standard uart pins are only used during debugging).
I am writing the rs232 data to a file instead of simply printing it out on the screen (I am using ESPlorer v0.2.0) because the uart.alt(1) command redirects the serial port to the alternative ESP8266 gpio pins.
I think I am doing something fundamentally wrong with the uart set up, but i can't tell what it is.
SOLVED:
It appears that you can't connect the ESP8266 to both the serial port for debugging (e.g. the serial port on a pc running ESPlorer) and also have the alternate serial pins (ESP8266 GPIO 13 and 15) connected (to an external serial device) at the same time.
The nodemcu uart.alt() function does not appear to "turn off" the standard serial i/o pins.
Disconnecting the pc from the standard serial i/o pins solved the problem (debugging becomes an issue, but there are work-arounds to resolve this).
(updated) one workaround is to use a simple telnet server to interact with the lua interpreter. you can either connect the ESP8266 to your wifi router or, even better, set it up as an access point (AP) so that all you have to do is to connect your computer to it and then simply telnet in (to the gateway's IP). so, in addition to the telnet code, you'll need set up the AP in your init.lua. full code for the telnet server and the AP setup is below. A nice benefit is that I can program and monitor the ESP8266 from my phone using an off-the-shelf telnet app!
jj = [[
sock = 22 -- just a placeholder, so it stays global. may not be needed.
-- use sock:send("hello") to insert your own custom output to the client.
telnet_srv = net.createServer(net.TCP, 180)
telnet_srv:listen(2323, function(socket)
local fifo = {}
local fifo_drained = true
local function sender(c)
if #fifo > 0 then
c:send(table.remove(fifo, 1))
else
fifo_drained = true
end
end
local function s_output(str)
table.insert(fifo, str)
if socket ~= nil and fifo_drained then
fifo_drained = false
sender(socket)
end
end
sock = socket -- make the socket globally available.
node.output(s_output, 0) -- re-direct output to function s_ouput.
socket:on("receive", function(c, l)
node.input(l) -- works like pcall(loadstring(l)) but support multiple separate line
end)
socket:on("disconnection", function(c)
node.output(nil) -- un-regist the redirect output function, output goes to serial
end)
socket:on("sent", sender)
print("Welcome to NodeMCU world.")
end)
]]
file.open("telnet.lua", "w")
file.write(jj)
file.close()
jj = [[
wifi.setmode(wifi.STATIONAP);
wifi.ap.config({ssid="ESPtest",pwd=""});
print("Server IP Address:",wifi.ap.getip())
dofile("telnet.lua")
]]
file.open("init.lua","w")
file.write(jj)
file.close()
node.restart()
output:
Server IP Address: 192.168.4.1 255.255.255.0 192.168.4.1
>

MQTT / ESP8266 / NodeMCU / Lua code not publishing

I have a problem with the following Lua code on an ESP8266...
function sendData(humidity,temperature)
-- Setup MQTT client and events
print("sendData() entered")
print("Setting up mqtt.Client...")
m = mqtt.Client(mqtt_client_id, 120, username, password)
print("Attempting client connect...")
m:connect(mqtt_broker_ip , mqtt_broker_port, 0, function(conn)
print("Connected to MQTT")
print(" IP: " .. mqtt_broker_ip)
print(" Port: " .. mqtt_broker_port)
print(" Client ID: " .. mqtt_client_id)
print(" Username: " .. mqtt_username)
payload = "Temp: " .. temperature .. " Hmdy: " .. humidity
m:publish("pt/env",payload, 0, 0, function(conn)
print("Going to deep sleep for " .. (DSLEEPTIME/1000) .. " seconds")
node.dsleep(DSLEEPTIME*1000,4)
end)
end)
end
The code is being successfully called with the following...
-- Connect to network
wifi.setmode(wifi.STATION)
wifi.setphymode(wifi_signal_mode)
wifi.sta.config(wifi_SSID, wifi_password)
wifi.sta.connect()
print("Attempting to connect...")
ip = wifi.sta.getip()
if ip ~= nil then
print("Got IP: " .. ip)
print("About to call sendData()...")
sendData(humidity, temperature)
print("Returned from sendData()...")
end
Using ESPlorer I see the following...
Attempting to connect...
Attempting to connect...
Attempting to connect...
Attempting to connect...
Attempting to connect...
Attempting to connect...
Got IP: 192.168.0.39
About to call sendData()...
sendData() entered
Setting up mqtt.Client...
Attempting client connect...
Returned from sendData()...
So it basically enters sendData(...) and I see the output from the line...
print("Attempting client connect...")
...but I never see the logging in the m:connect(...) block such as...
print("Connected to MQTT")
...it seems it simply returns immediately.
The MQTT broker is a Raspberry Pi running Mosquitto and I've tested it with apps on my Android phone and tablet. I get successful publishing / subscription between phone and tablet in both directions.
I'm a Lua novice and only understand the basics of MQTT and I'm at a loss for what's wrong with the m:connect(...) block if anyone can help it would be appreciated.
UPDATE: PROBLEM SOLVED - Apologies for not getting back to this thread sooner. The problem was simply down to the version of Mosquitto I was running on my RPi (which complied to MQTT v3.1). The NodeMCU MQTT library supports MQTT v3.1.1 and is NOT backward compatible. In essence there wasn't very much wrong with my code although I did make some changes - it was simply down to MQTT versions being incompatible.
You didn't tell us what NodeMCU version you use. Warning: do NOT use any of the pre-built 0.9.x binaries available at https://github.com/nodemcu/nodemcu-firmware/releases. Build your own firmware as per http://nodemcu.readthedocs.io/en/dev/en/build/.
I always helps to strip a failing function and to make use of all available callback functions. I can confirm the following works on a nearly 2 months old firmware from the dev branch sending data to cloudmqtt.com:
function sendData(humidity, temperature)
print("Setting up mqtt.Client...")
m = mqtt.Client("SO-36667049", 120, "user", "password")
print("Attempting client connect...")
m:connect("m20.cloudmqtt.com", 12703, 0, 0,
function(conn)
print("Connected to MQTT")
payload = "Temp: " .. temperature .. " Hmdy: " .. humidity
m:publish("topic", payload, 0, 0,
function(client)
print("Message sent")
end)
end,
function(client, reason)
print("Connection failed, reason: " .. reason)
end)
end
Differences:
m:connect defines secure y/n and autoreconnect y/n explicitly. It always confuses me if only a subset of all optional parameters is set. Is your 0 in m:connect interpreted as secure or as autoreconnect? I don't know Lua well enough to tell why I code it explicitly.
Make use of the extra callback for function for failed connection attempts. See http://nodemcu.readthedocs.org/en/dev/en/modules/mqtt/#connection-failure-callback-reason-codes for failure reason codes.
Do NOT use the same name for variables in callback functions as used in "parent" functions. Note how you use m:connect(..., function(conn) and then inside that function you use m:publish(..., function(conn) again. You don't interact with the conn object in your code, so no harm done. However, this may bite you in other projects.
Your code is looking fine. If m:connect fails nothing will happen as you did not provide a callback function for failed connection attempts.
Also you don't check m:connect's return value for success.
Refer to
http://nodemcu.readthedocs.org/en/dev/en/modules/mqtt/#mqttclientconnect
And check if your connection attempt fails.

Resources