This is more of a basic OOP question than a Kivy one. I have an app with 4 buttons. When I press one, I want to initialize a bluetooth connection from my laptop to an arduino uno and also schedule a function that sends bluetooth info every second.
I'm using the following code:
class HomeScreen(Screen):
def OnConnect(self):
print('Start')
port = "COM7"
#connect to bluetooth
bluetooth = serial.Serial(port, 9600)
print("Connected to HC-06")
bluetooth.flushInput()
#schedule a function that sends tester present to arduino
Clock.schedule_interval(self.SendData, 1)
def SendData(self,*args):
bluetooth.write(b"Boop")
Obviously "bluetooth" is not visible outside fct "OnConnect". I want bluetooth to be visible to both OnConnect & SendData but I only want to connect to the arudino when OnConnect is called. Any help is appreciated.
I've looked at the documentation at:
https://kivy.org/doc/stable/api-kivy.clock.html
It says:
If you want to schedule a function to call with default arguments, you can use the functools.partial python module:
So I would think something like this should work:
#schedule a function that sends tester present to arduino
Clock.schedule_interval(partial(self.SendData, bluetooth), 1)
def SendData(self, bt):
bt.write(b"Boop")
Related
Background:
I was given a task for college to implement an elevator's source code for an Arduino UNO with a user interface shield that contains: a 7-Segment display and a total of 8 buttons, one for each floor plus two to control the doors. The floor buttons also have an LED.
The hardware is only for human user input, but the brains is made entirely within Erlang. Before we got to implement this project in hardware, we used a simulation that uses wxWidgets to display the following UI: a window that displays the elevator doors, 6 more windows for each floor, and a window for the internal button array of the elevator. This button array is what I'm trying to implement within an Arduino.
Some code:
Our teacher gave us some confusing notes about the use of erlang:open_port/2 that I can't understand yet. The testing code we're using is the following:
-module(proUSB).
-export([start/1, order/2, loop/1, exit/2]).
start(Port_alias) ->
Port = open_port(Port_alias, []),
Pid = spawn(proUSB, loop, [Port]),
port_connect(Port, Pid),
{Port,Pid}.
order(Port,Value) ->
port_command(Port,Value).
loop(P) ->
receive
{P,{data,A}} ->
io:format("Received: ~p~n", [A]),
loop(P);
{'EXIT',P,_Reason} ->
port_close(P),
io:format("Unexpected finalization~n",[]);
exit ->
io:format("Proces finalization~n",[]);
Other -> io:format("Fi ~p~n",[Other])
end.
exit(Pid, Port) ->
port_close(Port),
Pid!exit.
As I've understood and successfully tested in Windows Subsystem for Linux (WSL) with the code mentioned above, all I have to execute in the Erlang shell is
> {Port, Pid} = proUSB:start("/dev/ttyS6").
{#Port<0.7>,<0.82.0>}
This will open the port. I can now send orders to the Arduino USART in the protocol we've designed. To light up the number three in the 7-segment display, we write
> proUSB:order(Port,"D3").
true
Now, if we press the floor button 1, you can see in the terminal
Received: "B1\n"
Received: "\n"
Received: "B1\n"
Received: "\n"
My question:
If I want to use Windows Powershell to do the same connection to the serial port, my teacher told us to write "COM6" instead of "/dev/ttyS6", but as I have tested, I can't get a connection but I get this error
> {Port, Pid} = proUSB:start("COM6").
** exception exit: einval
>
What am I missing? If WSL works with "/dev/ttyS6", why shouldn't it work with Windows when I can use the serial port with "RealTerm: Serial Capture Program"?
I have a respberry server and a windows client, both implemented in Python. The server transmits a BLE signal like a iBeacon signal.
Here is the code of the server:
import time
from bluetooth.ble import BeaconService
service = BeaconService()
uuid = "11111111-2222-3333-4444-555555555555"
major = 2 # 1 - 65535
minor = 1 # 1 - 65535
txpower = 1
interval = 200
service.start_advertising(uuid, major, minor, txpower, interval)
try:
time.sleep(300)
service.stop_advertising()
except KeyboardInterrupt:
print("cancelled")
finally:
service.stop_advertising()
print("Done.")
This code is working fine. I checked by installing an android app and I could find the device with that information.
Now I need to get that information in the windows client. In the windows client I'm using bleak library.
I have the following code to scan for beacon devices:
import asyncio
from bleak import discover
async def run():
devices = await discover()
for d in devices:
#if d.address == "B8:27:EB:03:5A:D6":
print(d.address, d.name, d.metadata, d.rssi)
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
The problem is when I check the console, I dont see the major, minor and UUID information:
There are showed other devices and I can see in one of them that the UUID is readable.
What I'm doing wrong here? Is bleak impossible to get the information I want? (minor, major) or am I transmitting in the wrong way? I dont think so because the mobile app is reading fine. Is there another library available to windows to get this information?
Thanks for the help. Have a good day.
Do not confuse the GATT Service UUID list returned by bleak with the iBeacon ProximityUUID you want. They are two totally different identifiers. The iBeacon ProximityUUID is encoded inside the manufacturer data returned by bleak. It will not parse it for you, but you could write a parser yourself. If you print out the manufacturer data bytes as hex you will see the pattern.
I wrote a Windows Beacon Library that does what you want. It is a port of the Android Beacon Library for Windows 10. But the documentation is sorely lacking. If you are stuck, I can help you use it, but it is designed to be used with Visual Studio languages not Python.
Using that library you can parse an iBeacon frame from BluetoothLEAdvertisementReceivedEventArgs in C# like this:
var beaconParser = new BeaconParser();
beaconParser.SetBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
Beacon beacon = beaconParser.FromAdvertisement(args.Advertisement, args.RawSignalStrengthInDBm, args.BluetoothAddress);
if (beacon != null)
{
OLogger.Debug("Found iBeacon: UUID=" + beacon.Id1 + " major=" + beacon.Id2 + " minor=" + beacon.Id3 + " rssi: " + beacon.Rssi);
}
I use a RN4020 BLE Module to communicate with the VALRT BT Button: https://vsnmobil.com/products/v-alrt/specs
Problem is, I need to send "80BEF5ACFF" within 30sec after connect to the specific private UDID "FFFFFFF5-00F7-4000-B000-000000000000" (see reference: https://github.com/HoyosIntegrity/V.ALRT-bluetooth-spec)
Problem is, I always get "ERR" back from RN4020.
Here is my Initialisation Code (which works):
sf,2 //Factory Reset
+ //echo on
sr,92000000 //configure as Master
r,1 //reboot
F //search devices
X //stop searching
E,0,001EC026C931 //connect to device with mac: 001EC026C931 which is my device
B //Bond
Get a "Connected" back and the Button quit it with a Beep.
Now I tried to Write
CUWV,FFFFFFF5-00F7-4000-B000-000000000000,80BEF5ACFF
with and without "-" but allways get a error back. At github are samples for Android and iOS but its not clear for me what I have to send...
Think I forgotten a prestep, but I dont know which one.
Strange is, when I connect and send "LC" I get this back:
180A
2A23,0012,02
2A24,0014,02
2A25,0016,02
2A26,0018,02
2A27,001A,02
2A28,001C,02
2A29,001E,02
2A2A,0020,02
1803
2A06,0025,0A
1802
2A06,0028,04
1804
2A07,002B,02
2A07,002C,10
180F
2A19,002F,02
2A19,0030,10
FFFFFFA000F74000B000000000000000
FFFFFFA100F74000B000000000000000,0034,0A
FFFFFFA200F74000B000000000000000,0037,02
FFFFFFA300F74000B000000000000000,003A,00
FFFFFFA300F74000B000000000000000,003B,10
FFFFFFA400F74000B000000000000000,003E,00
FFFFFFA400F74000B000000000000000,003F,10
FFFFFFA500F74000B000000000000000,0042,00
FFFFFFA500F74000B000000000000000,0043,10
END
That are some of the services but not all.
I can not find an OSC library for Arduino that supports Touch OSC's multitoggle controls. Am I doing something wrong, or is there a library that does have support for this control?
The library I'm using: https://github.com/recotana/ArdOSC
The OSC message I'm sending from Touch OSC:
/octobar/togglearray/2/2 1.
The Snippet relative to catch it on the Arduino:
server.begin(serverPort);
server.addCallback("/octobar/togglearray",&togglearray);
void togglearray(OSCMessage *_mes) {
Serial.println("Toggle Array");
}
I do have other callbacks working, and I have not pasted all of the server code here since it is working with fader and push button controls. The problem seems to be any control that supports multiple selection.
I have been trying to do almost exactly this and switched to the Z_Osc library as I could not work out how to parse the incoming messages using ArdOsc.
I do something like this:
rcvMes=server.getMessage();
mess=rcvMes->getZ_OSCAddress();
if (mess.startsWith("/1/multitoggle1/")) {
y=(mess.substring(16)).toInt();
x=(mess.substring(19)).toInt();
}
I have a Python script that writes short messages to the serial port on my Arduino Uno board using pySerial. There is a loop and depending on some conditions, multiple writes can happen within a loop, something like this:
while True:
#Conditions block 1
if <CONDITION1>:
serial.writelines("INIT")
elif <CONDITION2>:
serial.writelines("NEW")
...
#Conditions block 2
if <CONDITION1>:
# Fetch something from the Internet
serial.writelines("CHECK")
elif <CONDITION2>:
# Fetch something from the Internet
serial.writelines("STOP")
...
But, when my Arduino board receives this it receives the first message as INIT, but the second one is being read as INITSTOP or INITCHECK and third one gets concatenated to the previous messages. My arduino program checks for specific message in this way:
if(msg.equals("CHECK")) {
// Do something
}
else if(msg.equals("INIT")) {
// Do Something else
}
Can anyone guide me on this? BTW, I don't think the problem is with the Arduino as it works perfectly when I test it with the Serial Monitor available with the IDE.
I've tried adding sleeps of upto 10 seconds before every write, but that did not work out.
Try this this instead:
serial.write("INIT\r")
The writelines probably takes a list (but I can't check it now).