Serial communication with scilab in Linux - linux

Can you please provide some examples of serial communication with scilab in Linux. When I gave the command:
h=openserial(1,"9600,n,8,1");
I am getting the following error:
-->h=openserial(1,"9600,n,8,1");
!--error 999
TCL_EvalStr, at line 1
bad option "-mode": should be one of -blocking, -buffering, -buffersize, -encoding, -eofchar, or -translation
while executing
"fconfigure file114 -mode 9600,n,8,1"
at line 27 of function openserial called by :
h=openserial(1,"9600,n,8,1");

A simple serial communication with for example an Arduino device needs only the baudrate specified as the second argument in openserial. Seems like your other variables in the string argument (n?) are messing up.
Scilab 5.4 example, with Serial Toolbox, for com port 3 and baudrate 9600. 5s delay before trying to read serial.
h = openserial(3,"9600");
xpause(5000000);
data = readserial(h);
closeserial(h);
Together with some serial spamming code on your arduino device you should receive a string of data at each run in Scilab.
Example code for serial on Arduino device:
int cc=0;
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.println(cc);
if (cc<10){
cc++;
}
else{
cc=0;
}
delay(100);
}

Related

Error when reading/writing from CAN and sensor simultaneously over I2C

I am using a can board and an IMU MPU6050 to be able use motors while also reading an angle from the IMU.
When using them separately it works, the IMU reads and the CAN can activate and run the motors. The issue arises when both are activated at the same time and the script gives the following error:
IOError: [Errno 5] Input/output error
Here are the registers:
# MPU6050 Registers
MPU6050_ADDR = 0x68#0x0c
PWR_MGMT_1 = 0x6B
SMPLRT_DIV = 0x19
CONFIG = 0x1A
GYRO_CONFIG = 0x1B
ACCEL_CONFIG = 0x1C
INT_PIN_CFG = 0x37
INT_ENABLE = 0x38
ACCEL_XOUT_H = 0x3B
ACCEL_YOUT_H = 0x3D
And fault messages arises when I try to write a byte to the IMU at the same time as the CAN bus is activated:
# Write to Configuration register
bus.write_byte_data(MPU6050_ADDR, CONFIG, 0)
I created a new I2C bus for the IMU which is bus #3 which gives me the addresses 0x68 and 0x0c.
I have checked the wiring which is correct. Otherwise I should get the same error when running them separately.
Does anyone have any suggestions on what to try next?

Winsock 2 discovering Bluetooth devices only showing previously paired devices

I am currently trying to use the WINSOCK 2 API in order to discover available Bluetooth devices near by. I am using code which is based on a Microsoft example which can be found here.
I am mainly using WSALookupServiceNext to iterate through the available devices. The issue is that I only get a list of previous paired Bluetooth devices, and I am not seeing any other devices. I added some code in order to print device information:
*********************
Winsock search started!
*********************
Device #:1
Device name:MagicBox II
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x00025b3dc371, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:2
Device name:Mpow Flame
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x501801101c68, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:3
Device name:WH-1000XM2
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x702605aba41d, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Device #:4
Device name:Magicbuds
Device connected: 0
Device remembered: 1
Device authenticated: 1
Remote Bluetooth device is 0x5017032a701b, server channel = 0
Local Bluetooth device is 0x84ef18b8460a, server channel = 0
Here is the corresponding code section, ( I did call WSAStartup beforehand):
void WSALookupAvailableDevices(void)
{
WSAQUERYSET wsaQuery{};
LPWSAQUERYSET pwsaResults{};
HANDLE hLookup{};
CSADDR_INFO *pAddrInfo{};
SOCKADDR_BTH *pBtSockRemote{},
*pBtSockLocal{};
char buffer[4096] = {};
int nDevicesFound = 1;
DWORD swSize = sizeof(buffer);
DWORD flags = LUP_RETURN_ADDR | LUP_RETURN_NAME | LUP_RES_SERVICE | LUP_CONTAINERS | LUP_RETURN_BLOB | LUP_RETURN_TYPE;
/*Preparing the query set*/
wsaQuery.dwNameSpace = NS_BTH;
wsaQuery.dwSize = sizeof(WSAQUERYSET);
if (WSALookupServiceBegin(&wsaQuery, flags, &hLookup) == SOCKET_ERROR)
{
wprintf(L"Shit something went wrong! error: %d!\n", WSAGetLastError());
return;
}
wprintf(L"*********************\n");
wprintf(L"Winsock search started!\n");
wprintf(L"*********************\n\n");
/*Preparing the queryset return buffer*/
pwsaResults = (LPWSAQUERYSET)buffer;
pwsaResults->dwNameSpace = NS_BTH;
pwsaResults->dwSize = sizeof(WSAQUERYSET);
while (WSALookupServiceNext(hLookup, flags, &swSize, pwsaResults) == NO_ERROR)
{
pAddrInfo = (CSADDR_INFO*)pwsaResults->lpcsaBuffer;
pBtSockRemote = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->RemoteAddr.lpSockaddr);
pBtSockLocal = (SOCKADDR_BTH*)(pwsaResults->lpcsaBuffer->LocalAddr.lpSockaddr);
wprintf(L"Device #:%d\n", nDevicesFound);
wprintf(L"Device name:%s\n", pwsaResults->lpszServiceInstanceName);
wprintf(L"Device connected: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_CONNECTED));
wprintf(L"Device remembered: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_REMEMBERED)>0);
wprintf(L"Device authenticated: %d\n", (pwsaResults->dwOutputFlags & BTHNS_RESULT_DEVICE_AUTHENTICATED)>0);
wprintf(L"Remote Bluetooth device is 0x%04x%08x, server channel = %d\n",
GET_NAP(pBtSockRemote->btAddr), GET_SAP(pBtSockRemote->btAddr), pBtSockRemote->port);
wprintf(L"Local Bluetooth device is 0x%04x%08x, server channel = %d\n",
GET_NAP(pBtSockLocal->btAddr), GET_SAP(pBtSockLocal->btAddr), pBtSockLocal->port);
nDevicesFound++;
}
WSALookupServiceEnd(hLookup);
wprintf(L"\n");
}
Thanks for the help in advance!
LUP_FLUSHCACHE is what you need. And yes, it will always return paired device (in addition to discovered). I mean that if device paired WSALookup returns it in the list even it is not available (turned off or out of range).
https://learn.microsoft.com/en-us/windows/desktop/bluetooth/bluetooth-and-wsalookupservicebegin-for-device-inquiry
DWORD flags = LUP_RETURN_ADDR | LUP_RETURN_NAME | LUP_RES_SERVICE | LUP_CONTAINERS | LUP_RETURN_BLOB | LUP_RETURN_TYPE | LUP_FLUSHCACHE;
But the best way to discover devices is to use this flags set.
DWORD flags = LUP_RETURN_ADDR | LUP_CONTAINERS | LUP_FLUSHCACHE;
Also it is good idea to provide additional information (BTH_QUERY_DEVICE) so you can set discovering timeout and other params
BTH_QUERY_DEVICE qDev;
qDev.LAP = 0;
qDev.length = bTimeout; // Timeout in seconds
BLOB Blb;
Blb.cbSize = sizeof(BTH_QUERY_DEVICE);
Blb.pBlobData = (PBYTE)&qDev;
QuerySet.lpBlob = &Blb;
https://learn.microsoft.com/th-th/windows/desktop/api/ws2bth/ns-ws2bth-_bth_query_device
After discovering completed (please note that WSALookupServiceBegin takes time (blocks) until discovering finished) you can use BluetoothGetDeviceInfo to get extended information such as device's name and other info.
https://learn.microsoft.com/en-us/windows/desktop/api/bluetoothapis/nf-bluetoothapis-bluetoothgetdeviceinfo
You should know that because of some Bluetooth limitations name resolution can be executed only after discovering completed. And this operation may take time. So if you call to BluetoothGetDeviceInfo right after discovering completed you can still get empty device name for new discovered devices (devices that was not previouslt discovered).
There is not easy way to resolve this issue except switch to WinRT API or wait for some time before reading device name. You also can use WM_DEVICECHANGE message to get notification about device name resolution
https://learn.microsoft.com/en-us/windows/desktop/bluetooth/bluetooth-and-wm-devicechange-messages
And there is one more problem: MS stack always returnsd paired devices during discovering even they are not available.

What causes "resource temporarily unavailable" in v4l2

I have compiled adv7180 driver available here.
I am unloading the ov5642 cameradriver(which in my case is built-in) and loading the adv7180_tvin module and after I am loading mxcv4l2_capture module which creates video0 in /dev/.
(dmesg command says: "mxc camera on IPU2_CSI1 registered as video0")
But when I try to access video0 with v4l2-ctl I got a message "resource temporarily unavailable" or when I am using gstreamer I got message "Can not open /dev/video0" (but the device is really created).
Is that a problem in device tree settings or it can be caused by something else? Which tools should I use to find out what causes this issue?
My device tree settings look like below:
&i2c3{
adv7180: adv7180#20{
compatible = "adv,adv7180";
reg = <0x20>;
clocks = <&clks IMX6QDL_CLK_CKO2>;
clock-names = "csi_mclk";
pwn-gpios = <&gpio3 10 GPIO_ACTIVE_LOW>;
ipu_id = <1>;
csi_id = <1>;
mclk = <24000000>;
mclk_source = <0>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hummingboard2_parallel>;
cvbs = <1>;
};
};
I need to add that before adv7180 I was using above settings for ov5642 camera (excluding cvbs setting) and everything worked properly.
EDIT:
Ok I got one clue.
When I load modules in dmesg message "mxc_v4l2_master_attach: ipu(0:1)/csi(1:1)/mipi(0:0) doesn't match" shows.
But it only happens when ipu_id=<1> in v4l2_cap device tree settings and in adv7180 settings. When i change ipu_id to ipu_id=<0> in v4l2 settings and adv7180 dmesg now shows "parallel attach to IPU1 CSI1 and I can access the /dev/video0 succesfully with v4l2-ctl tool.
But In my case there is only one possibility to use IPU2_CSI1.
Why can't I set IPU2 to adv7180 when I was using it successfully to ov5642 ?
As per my knowledge i.MX6 having two IPUs. I think by default IPU1 parallel interface is not enabled in the board file. So you need to check the IOMUXC_GPR1 register setting (bit 19 and 20) for IPU/CSI1 and pass the csi_id in your camera driver.
As you are using the parallel interface so check your pin muxing setting as well in your device tree. (which is not required for serial interface.)
Edit:
There are two ways which you can follow to update the register setting from the kernel space (boardfile or camera driver) itself:
1. From the board file:
struct regmap *gpr
gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
regmap_update_bits(gpr, IOMUXC_GPR1, 1 << 20, 1 << 20);
2. From the boardfile or camera driver
void __iomem *va_ipu2_address;
u32 reg_val;
va_ipu2_address = ioremap(0x20e0004,0xe0004);
reg_val = readl(va_ipu2_address);
/* Enable parallel interface to IPU2 CSI1. */
writel(reg_val | 1 << 20, va_ipu2_address);
Thanks for Your answer.
My pinmuxing looks like this:
&iomuxc{
hummingboard2{
pinctrl_hummingboard2_parallel: hummingboard2_parallel{
fsl,pins = <
MX6QDL_PAD_EIM_A24__IPU2_CSI1_DATA19 0x0b0b1
MX6QDL_PAD_EIM_A23__IPU2_CSI1_DATA18 0x0b0b1
MX6QDL_PAD_EIM_A22__IPU2_CSI1_DATA17 0x0b0b1
MX6QDL_PAD_EIM_A21__IPU2_CSI1_DATA16 0x0b0b1
MX6QDL_PAD_EIM_A20__IPU2_CSI1_DATA15 0x0b0b1
MX6QDL_PAD_EIM_A19__IPU2_CSI1_DATA14 0x0b0b1
MX6QDL_PAD_EIM_A18__IPU2_CSI1_DATA13 0x0b0b1
MX6QDL_PAD_EIM_A17__IPU2_CSI1_DATA12 0x0b0b1
MX6QDL_PAD_EIM_DA11__IPU2_CSI1_HSYNC 0x0b0b1
MX6QDL_PAD_EIM_DA12__IPU2_CSI1_VSYNC 0x0b0b1
MX6QDL_PAD_EIM_A16__IPU2_CSI1_PIXCLK 0x0b0b1
MX6QDL_PAD_EIM_DA10__GPIO3_IO10 0x400130b1
>;
};
};
};
and it's been working succesively with ov5642 camera.
No I see that the adv7180 driver does not take an ipu_id as an argument from device tree so I think it is using the default ipu which is (I think) IPU1.
I've been playing arround how to change settings in IOMUXC_GPR1. Bit 20 needs to be set ("enable parallel interface to IPU2 CSI1). But have got no more ideas how to do it in device tree.
Ok. I found it !
I couldn't set bit 20 in IOMUXC_GPR1 register using mach-imx6q.c file so I did it this way:
in console:
sudo devmem2 0x20e0004
and read the existing value (which was in my case 0x48643005). Then I set bit 20 to one ("1") so I got 0x48743005 and I put this value into the register:
sudo devmem2 0x20e0004 w 0x48743005
next I loaded adv7180_tvin and mxc_v4l2_capture modules and captured frames using gsreamer:
gst-launch-1.0 imxv4l2videosrc device=/dev/video0 ! imxipuvideotransform ! autovideosink deinterlace=true
Everything works great ! Thanks for help !

Pin Muxing in linux kernel

I want to do following pin muxing.
i.e USART Tx -> to GPIO -> Back to USART Tx pin inside Linux kernel for some purpose.
I tried to make the PIN as GPIO using gpio_request and gpio_direction_output, so i am able to make that pin as GPIO . But as i want to switch back from GPIO to USART Tx pin, it is not working, I tried following at91_set_A_periph to that pin, still no luck.
Working on kernel : 3.18 and at91 atmel board.
You can have a look at the i2c-imx driver. It does exactly that.
You need to use pinctrl_lookup_state to retrieve the different pinctrl states (one of those being USART Tx and the other one GPIO). Then you can switch between both with pinctrl_select_state.
To sum it up, you'd have something like that in your uart node:
usart3: serial#fc00c000 {
pinctrl-names = "default","gpio";
pinctrl-0 = <&pinctrl_usart3>;
pinctrl-1 = <&pinctrl_usart3_gpio>;
tx-gpio = <&pioE 4 GPIO_ACTIVE_LOW>;
status = "okay";
};
In the driver code:
pinctrl_pins_default = pinctrl_lookup_state(pinctrl, PINCTRL_STATE_DEFAULT);
pinctrl_pins_gpio = pinctrl_lookup_state(pinctrl, "gpio");
tx_gpio = of_get_named_gpio(pdev->dev.of_node, "tx-gpio", 0);
Then, you can use pinctrl_select_state to switch back and forth between pinctrl_pins_default and pinctrl_pins_gpio. tx_gpio is your gpio.

RaspBerry pi B rev2 - Issue while sampling a LM335 (temp. sensor) thru a MCP3208 ADC via SPI in Python 3

I tried to interface a RaspBerry pi with a LM335 temperature sensor this week-end. I'm using a MCP 3208 micro controller (channel 0) to interface the sensor. My goal is to collect samples data in SPI mode with python 3 scripts (classes).
I've checked the wiring and everything seems OK for me, I'but I'am a beginner, not really aware of Electronic concepts.
On the software side , I've installed quick2wire that claims to be python 3 compatible. In fact I want to lead the micro-controller with Python 3 API's (not thru shell calls)
Components
Raspberry pi REV2 model B with Rasbian-wheezy / Quick2wire installed. /dev/spix.y devices are listed.
MCP3208 ADC : 12 bits ADC / SPI. I'm using CS0 from the GPIO. The sensor is connected to channel 0 (B). see datasheet.
LM335 : temperature sensor. Outputs 10mV / °K. Min 5muA / Max 5 mA. It's connected to the MCP3208 channel #0 (A). see datasheet
220 ohms resistor (C). set up regarding LM335 outputs and desired temperature range coverage with my own calculations : May be a problem ...
Schematics extract
The LM335 (zener diode like) is connected as :
Wiring
Components are wired as shown bellow. Note that the yellow link is connected behind the cobbler kit on the CS0 SPI channel.
Quick2wire
I use the bellow script to query the CS0/Channel 0 GPIO interface. Unfortunately, I've not found usefull informations on the quick2wire-python-api API's. I've just copy/paste an example found as it was written in the same goal. I'm not sure if it really works :
#!/usr/bin/env python3
from quick2wire.spi import *
import sys, time
try:
channel = int(sys.argv[1])
except:
channel = 0
MCP3208 = SPIDevice(channel, 0)
while True:
try:
response = MCP3208.transaction(writing_bytes(0x41, 0x13), reading(1))
print ("output = %i" % ord(response[0]))
time.sleep(1)
except KeyboardInterrupt:
break
The script outputs :
output = 0
output = 0
output = 0
output = 0
output = 0
....
The result is the same with the channel 1 ( with argv = 1)
As the MCP3208 Din (probe output) receives voltage (see bellow) quick2wire should read at 18°C (rawghly my home inside temperature today)
3,3 V / 2^12 = 805 muA as I understand as "digital step"
18°C + 273°C = 291 => 2,91 V on the micro controller Din pin
and then return 2 910 / 0.805 = 3 615
Am I wrong ?
Controls
I've no oscilloscope, the only measures I can read are :
Voltage is 2.529 V at B checkpoint and 0,5 V (+/-5%) on the other MCP3208 channels
Note : the adjust pin is not used on the LM335 so results way not be accurate but voltage is here !
Seems to be a problem on the quick2wire side I think. But which ?
Code
The quick2wire.spi.SPIDevice class lakes of détails on the transfers parameter in terms of structure, content and output response format.
def transaction(self, *transfers):
"""
Perform an SPI I/O transaction.
Arguments:
*transfers -- SPI transfer requests created by one of the reading,
writing, writing_bytes, duplex or duplex_bytes
functions.
Returns: a list of byte sequences, one for each read or duplex
operation performed.
"""
transfer_count = len(transfers)
ioctl_arg = (spi_ioc_transfer*transfer_count)()
# populate array from transfers
for i, transfer in enumerate(transfers):
ioctl_arg[i] = transfers[i].to_spi_ioc_transfer()
ioctl(self.fd, SPI_IOC_MESSAGE(transfer_count), addressof(ioctl_arg))
return [transfer.to_read_bytes() for t in transfers if t.has_read_buf]
Another question :
how to set SPI configuration values like mode, clock speed, bits per word, LSB ... and so on.
Thanks in advance for your help.
I know you probably intend to learn how to use the ADC, an so this isn't really an answer to your question (I will use your very rich post for sure - thanks), but I'm aware of temperature sensors that already pack data in GPIO serial line, that are best suited for the raspberry.
You really have to read this awesome tutorial, if you haven't already.

Resources