WebUSB and FTDI232 - webusb

I try to connect to a serial-usb interface (FT232) but can't find anything on how to configure it...
What I've got :
A serial to USB interface from FTDI, it's a TTL-232RG-VSW5V-WE from this page
A custom board sending messages through RS232
What I need :
I need to connect to this interface using WebUSB, send messages, read messages.
What I've achieved :
Right now, I can connect to the interface and "read" something.
My problem :
I can't find anything on the web on how to configure the USB interface, the serial port configuration must be 57600 baud/s, E, 8, 1 but nothing I could find told how to configure these values...
See the following code, from what I understood, I've got to put some value in the controlTransferOut but I can't find what to put and why..
device = await navigator.usb.requestDevice({ 'filters': [] });
console.log(device);
await device.open();
if (device.configuration === null) {
await device.selectConfiguration(1);
}
await device.claimInterface(0);
await device.selectAlternateInterface(0, 0);
await device.controlTransferOut({ /* WHAT DO I PUT HERE?? */ });
let result = await device.transferIn(1, 64);
console.log((new TextDecoder).decode(result.data));
What I can read from the "What I've achieved" section is single chars because the serial is not well configured.
I tweaked it though to kindda make it work, I've opened the serial port with another software, configured it, closed the other software, then connect to the USB interface with webusb and read messages. That worked, but way to complicated...
Any help would be REALLY appreciated :)

According to the datasheet your TTL-232RG-VSW5V-WE cable contains a FT232R chip. The datasheet for that is here. I was hoping to discover a description of the protocol that the chip supports but all I found was documentation for their proprietary drivers.
On the other hand I know that Linux supports these chips so there must be code in the kernel driver for setting baud rate. The function in question is change_speed() in ftdi_sio.c.
From this it appears that the control transfer you need to send is,
device.controlTransferOut({ requestType: 'vendor',
recipient: 'device',
request: 3 /* FTDI_SIO_SET_BAUDRATE_REQUEST */,
value: divisor_value,
index: divisor_index });
divisor_value and divisor_index are the lower and upper 16 bits of the chip's clock divisor which is calculated by the ftdi_232bm_baud_to_divisor function based on the baud rate requested.
Hopefully this is a good start towards reading the code and figuring out what you need.

Thank you, very much. It works like a charm.
I figured out for baud rate 9600:
device.controlTransferOut({
requestType: "vendor",
recipient: "device",
request: 3 /* FTDI_SIO_SET_BAUDRATE_REQUEST */,
value: 16696, // divisor_value
index: 48000000 // divisor_index
});

Related

Using Noble to communicate with BLE device

I have spent the last couple of days researching and understanding GATT to control my new adjustable bed which I can currently only control via Manufacturer's app but I want to control via my smart home setup.
I am able to get characteristics which are read and write with/without response so I know I am on right track and I have used PacketLogger on OSX to get values which I now know are acceptable when sent by myself using an IOS app called BLE Scanner which just asks for a Hex or Text Value to send to the characteristics for the device (bed) and I have sent the values I extracted from PacketLogger when using the manufacturer's app (5212 006E 0100 4EBD) as Hex separately and it vibrates the bed!
I just need to be able to this myself now with Noble by sending either straight to the peripheral.writeHandle function or via the characteristic.write function. I have tried many different things but I don't get the same effect as BLE Scanner app when it sends the values individually as Hex so I know the device isn't happy with what i'm sending. I noticed there is some padding added for what I think is L2CAP but as I say BLE Scanner just works for (5212 006E 0100 4EBD) as long as they are sent separately as Hex.
Would really appreciate some help to get me over the line.
I have tried so far to write to the characteristic and also tried direct to the periphel as there is no mention of the characteristic UUID in the PacketLogger logs when writing via BLE Scanner whereas when using the Manaufacturer app PacketLogger shows the write characteristic UUID so both I think will work.
I have tried many variations of
peripheral.writeHandle(18, Buffer.from("5212006E01004EBD", "hex"),
true, function(err) { console.log('writehandle'+err) });
and
characteristic.write(Buffer.from("5212006E01004EBD", "hex"), true,
function (error) {
if (!error) {
console.log("write succesful");
} else {
console.log("write unsuccesful");
}
}.bind(this));
I do see a difference in the ATT Send PacketLogger entry for the BLE Scanner App which works and my attempt in Noble which doesn't work - Write Request - Handle:0x0012 - Value: 5212 006E 0100 4EBD Opcode is 0x0012 is the working packetlogger entry for BLE Scanner whereas my attempt shows multiple entries for each attempt and the first entry is always Exchange MTU Request - MTU: 104 and the Opcode is 0x0002. No matter what I change in Noble the Opcode remains the same.

Web Bluetooth: Want to filter on manufacturer data when using navigator.bluetooth.requestDevice

I see that Google Chrome has not implemented filtering on manufacturer data. Issue 707635, does not seem to have any progress.
The Web Bluetooth specification has an (unstable) spec for filtering manufacturerData when using navigator.bluetooth.requestDevice (https://webbluetoothcg.github.io/web-bluetooth/#example-filter-by-manufacturer-service-data
Does anyone know if there is any progress on this or made this kind of filtering work?
Following our discussion, I've added support for manufacturer data filter in Web Bluetooth in Chrome 92. See https://crbug.com/707635
Here's an example:
// Filter Bluetooth devices from Google company with manufacturer data bytes
// that start with [0x01, 0x02].
navigator.bluetooth.requestDevice({
filters: [{
manufacturerData: [{
companyIdentifier: 0x00e0,
dataPrefix: new Uint8Array([0x01, 0x02])
}]
}],
optionalServices: ['battery_service'] // Required to access service later.
})
.then(device => { /* … */ })
.catch(error => { console.error(error); });
You'll find a sample at https://googlechrome.github.io/samples/web-bluetooth/manufacturer-data-filter.html and some developer documentation at https://web.dev/bluetooth/#manufacturer-data-filter
Let me know if that works for you ;)
The Chrome team has NOT made progress on this yet as you've noted. In the mean time, would filtering by device name, device name prefix, or GATT services work out for you?
You can try it with https://googlechrome.github.io/samples/web-bluetooth/device-info.html.
Short answer:
'Star' issue 707635 to receive updates and signal interest.
If you have a clear example / business case to share consider adding a comment to help developers understand how to prioritize this work.
Chromium is open source, consider contributing or finding a developer to do this work.

Johnny-Five, I2C, Controlling multiple temperature sensors using ESP8266

I'm trying figure out how to control multiple temperature sensors.
THE SETUP:
2 ESP8266 Micro Controllers
2 MCP9808 Temperature Sensors
1 Machine controlling both ESPs using Johnny-Five.
NOTE: Each ESP8266 micro controller handles one MCP9808 Temperature Sensor.
THE GOAL:
The central machine (MacOS running Johnny-Five) handles both microcontrollers under one Node JS script.
THE PROBLEM:
I can control one Micro Controller / Temperature pairing, but not both under the same script.
Apparently the key to handling both at once lies in knowing how to handle the IC2 addressing.
So far I haven't been able to find any pages, forums, instructions or combinations thereof that clearly explain the logic in terms that I can understand.
THE QUESTION:
How to handle I2C using Johnny-Five to control multiple devices
THE CODE:
It only works when handling one Sensor, not both
In other words with the 4th line commented out it works. Uncommented, it doesn't.
var five = require("johnny-five");
var {EtherPortClient}=require("etherport-client");
var Thermometers=[
//{Name:"Thermometer1", Ip:"192.168.1.101"}, //Uncommenting causes fail.
{Name:"Thermometer2", Ip:"192.168.1.102"}
];
TrackThermometers();
function TrackThermometers(){
Thermometers.forEach(function(ThisThermometer, ThermometerCount){
ThisThermometer.Board=new five.Board({
port: new EtherPortClient({
host: ThisThermometer.Ip,
port: 3030
}),
repl: false
});
ThisThermometer.Board.on("ready", function(){
ThisThermometer.Controller=new five.Thermometer({ //This cmd triggers the error
controller:"MCP9808"
});
ThisThermometer.Controller.on("change", function(){
console.log(this.id, this.fahrenheit);
});
})
});
}
SOLUTION
There is a board property (undocumented as of this post) under the J5's Thermometer API. Assigning the Board instance in question to that property associates the Thermometer instance with that board.
By way of example the above code would be edited as follows...
ThisThermometer.Controller=new five.Thermometer({
board: ThisThermometer.Board, //<-- the missing magic
controller:"MCP9808"
});
Thanks to Donovan Buck for figuring this out. May be documented soon.

Unable to detect Seeedstudio Bluetooth Shield

I have a problem regarding Seeedstudio Bluetooth shield http://www.seeedstudio.com/depot/Bluetooth-Shield-p-866.html
I can't detect its presence by any other devices.
The code I uploaded to Arduino is a standard example for slave device from the library:
/* Upload this sketch into Seeeduino and press reset*/
#include <SoftwareSerial.h> //Software Serial Port
#define RxD 6
#define TxD 7
#define DEBUG_ENABLED 1
SoftwareSerial blueToothSerial(RxD,TxD);
void setup()
{
Serial.begin(9600);
pinMode(RxD, INPUT);
pinMode(TxD, OUTPUT);
setupBlueToothConnection();
}
void loop()
{
char recvChar;
while(1)
{
if(blueToothSerial.available()){//check if there's any data sent from the remote bluetooth shield
recvChar = blueToothSerial.read();
Serial.print(recvChar);
}
if(Serial.available()){//check if there's any data sent from the local serial terminal, you can add the other applications here
recvChar = Serial.read();
blueToothSerial.print(recvChar);
}
}
}
void setupBlueToothConnection()
{
blueToothSerial.begin(38400); //Set BluetoothBee BaudRate to default baud rate 38400
blueToothSerial.print("\r\n+STWMOD=0\r\n"); //set the bluetooth work in slave mode
blueToothSerial.print("\r\n+STNA=SeeedBTSlave\r\n"); //set the bluetooth name as "SeeedBTSlave"
blueToothSerial.print("\r\n+STOAUT=1\r\n"); // Permit Paired device to connect me
blueToothSerial.print("\r\n+STAUTO=0\r\n"); // Auto-connection should be forbidden here
delay(2000); // This delay is required.
blueToothSerial.print("\r\n+INQ=1\r\n"); //make the slave bluetooth inquirable
Serial.println("The slave bluetooth is inquirable!");
delay(2000); // This delay is required.
blueToothSerial.flush();
}
I've uploaded it to Arduino UNO, connected the shield and... Nothing.
LED marked as D1 is blinking green, and D2 is switched off. The device is not detected by none of the three devices I've tried (two computers and a smartphone).
By "not detected" I mean "hcitool returns nothing and OS based search for Bluetooth devices reports nothing". All three devices can detect each other without any problems.
I tried to connect it to other UNO board (in case the first one was damaged), but the result is the same.
I thought that the shield is somehow at fault, so I had it replaced by a new one - but the results are still the same.
Summing up:
3 extrnal devices
2 Arduinos
2 shields
Tested in all possible combinations, and still no success.
The device is powered up, because when I set it to send it's status to A1 analog port I always read 0 instead of a random value.
The only logical conclusion is that there is something wrong with the code above, but every google search I've made pointed me exactly to that file. It's from official wiki and in every example I've found. I've tried to contact Seeedstudio about it, but they didn't have anything of value to add ("try rebooting until it works").
Has anyone had similar problem, or has any advice what's wrong with the code?
I've managed to solve the problem on my own.
Two steps were required:
First of all I had to use hardware serial port (ports 0 and 1 on Arduino UNO), because for some reason SoftwareSerial doesn't work well with this shield.
Then I had to battery as power supply, since serial communication via ports 0 and 1 has lower priority than USB serial.
The disadvantage of this solution is that you lose USB communication with your PC, but fortunately I didn't need it.
EDIT: To avoid any confusion, here is an example of the code which worked for me:
void setup()
{
setupBlueToothConnection();
Serial.flush();
}
void loop()
{
for (char i = 0; i <= 254; i++)
{
Serial.print(i);
delay(1000);
}
}
void setupBlueToothConnection()
{
Serial.begin(38400); //Set BluetoothBee BaudRate to default baud rate 38400
Serial.print("\r\n+STWMOD=0\r\n"); //set the bluetooth work in slave mode
Serial.print("\r\n+STNA=SeeedBTSlave\r\n"); //set the bluetooth name as "SeeedBTSlave"
Serial.print("\r\n+STOAUT=1\r\n"); // Permit Paired device to connect me
Serial.print("\r\n+STAUTO=0\r\n"); // Auto-connection should be forbidden here
delay(2000); // This delay is required.
Serial.print("\r\n+INQ=1\r\n"); //make the slave bluetooth inquirable
//Serial.println("The slave bluetooth is inquirable!");
delay(2000); // This delay is required.
Serial.flush();
}
Please note that the modem sends answers to some of the commands, you should clean Serial buffer before reading from it.
Also, the jumpers on the shield should be connected like this: BT_TX to pin 0 and BT_RX to pin 1.

nodejs - reading from the serial port

I've been looking around for an answer on this...
Basically, I want to read data from the serial port (in this case, over USB). I've looked into the node-serialport module but it keeps stalling after the first result form the serial port. I expected it to just spit out the data when it received it. It's as if a buffer is filling up and needs to be flushed somehow?
I've slightly modified the code from the demos I found here - https://github.com/voodootikigod/node-serialport/tree/master/tests
Here's my code:
var sys = require("sys"),
repl = require("repl"),
serialPort = require("serialport").SerialPort;
// Create new serialport pointer
var serial = new serialPort("/dev/tty.usbmodem1d11" , { baudrate : 9600 });
// Add data read event listener
serial.on( "data", function( chunk ) {
sys.puts(chunk);
});
serial.on( "error", function( msg ) {
sys.puts("error: " + msg );
});
repl.start( "=>" );
I'm using an Arduino hence the 9600 baudrate.
Any help would be awesome, cheers,
James
Author of node-serialport. I have tracked down the issue and it is due to a compilation issue with IOWatcher in node.js. I have revised the strategy for reading from the serial port and it now should function as designed in all cases. Please ensure you are using node-serialport 0.2.6 and greater.
Now go out and build JS controlled robots!!!
I also experienced problems with the serial port read.
This is due to a bug in node.js v4.7 (see this issue)
However it worked after switching to an older version of Node.js (v4.0).
It might work with versions up to v4.6 also, but I haven't verified that yet.

Resources