STM32 CAN controller gets arbitration lost transmitting at 500 Kbit/s - stm32

My APB1 clock is reported by the STM32 library as being 36MHz.
I used a website to calculate a prescaler value of 3 (4 with the automatic +1), BS1 of CAN_BS1_15tq and BS2 of CAN_BS2_2tq. When I use the values in a quick spreadsheet calculation they come out right for a 500 Kbit/s baud rate.
I used different values, but assuming the same clock speed of 36 MHz to talk at 250 Kbit/s baud rate to NMEA 2000 devices successfully. When I run my code at 250 Kbit/s it works correctly and talks to my test board (which is using the same code) successfully.
I wondered if the TX and RX pin GPIO speed mattered. Here is my configuration for those pins:
gpio_init_data.GPIO_Speed = GPIO_Speed_10MHz;
gpio_init_data.GPIO_Pin = CAN1_RX;
gpio_init_data.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(CAN1_PIN_GROUP, &gpio_init_data);
gpio_init_data.GPIO_Pin = CAN1_TX;
gpio_init_data.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(CAN1_PIN_GROUP, &gpio_init_data);
When I run at 500 KBit/s baud rate I get all transmissions failing and arbitration lost flagged: TSR=41000004. This happens even with the RX and TX pins at GPIO speed 50 MHz.
The CAN transceiver is an ISO1050 which, according to the data sheet, can handle up to 1 Mbit/s.
Does anyone have any idea what I could be doing wrong? Could it be a problem in the circuitry?

As Lundin said, "CAN transceivers need an ideal impedance of 60 ohm to work properly."
The system I am using is a test rig with a board to be tested connected to a test board by about 8cm of CAN bus cable pair. Up to speeds of 250 Kbits this works perfectly well, but not at 500 Kbits.
Adding a 56 ohm resistor (2 x 120 ohm may be better) solves the problem.
Many thanks to Lundin for his patience and excellent information.

Related

STM32F429 GPIO DMA Read and Write

Hello,
I'm making a project where I want to bit-bang the JTAG protocol.
According to the AN4666 provided by ST, DMA + GPIO can achieve high speeds in bit-banging synchronous protocols.
I want to:
Generate N PWM pulses (the CLK signal).
With the falling edge of each pulses, I want to set some GPIO with DMA.
With the rising edge, I want to read from the GPIO using DMA.
What is the best way to achieve these specs using HAL?
even withtout dma you can reach quite high freq bit banged i/o i'll say in range 2 - 10MHz assuming fast enougth mcu and gpio bus clock high enough (48 96MHz)
Clock just wan't be as stable and may suffer "stall" say idle time when iterrupt occur vs dma. but is way simpler
for DMA base , if you use 3 bit of one port, one for clk and one for TDI and one for TDO then use 2 dma one to wr and one that rd on same timer source (if possible) at double rate of the TCK signal
the data in is rebuilt by taking teh i bit of one read data over 2
index like 0 2 4 or 1 3 5 ... depending on edge you want and how you wr clk array in mem is coded.
last if your jtag chain is 8 bit multiple SPI is even simpler and dma easy ;)

STM32 generate 22Mhz clock on gpio out from SystemCoreClock 110Mhz

I want to generate clock for PCA9959 LED driver with my STM32L552. The LED driver needs an external clock at 20 MHz (+/- 15%). I'm trying to generate a 22 MHz clock on port PA8 on STM32L552. I managed to generate a PWM on port PA8, but I can't reach the frequency of ~22Mhz. I arrive at a maximum of 8Mhz.
Here are the PWM parameters:
I'm not sure I filled in the pwm parameters correctly. Normally with his settings I guess I should have a 22 MHz PWM with a 20% duty cycle.
PWM (MHz) = SystemCoreClock (MHz) / Prescaler => 22MhZ = 110MHz / 5
My clock configuration:
Thanks for your help.
The easiest way to output a high speed clock like this is with the MCO peripheral, rather than a timer. Fortunately for you the MCO pin is PA8. Perhaps the person who designed your board knew this and intended you to use MCO. Read the reference manual to see how.
If you do want to use a timer to do 22MHz, then as you have correctly identified you cannot get a 50% duty-cycle on your PWM. I would recommend starting with a 40% or 60%, with an output-compare value of 2-out-of-5 or 3-out-of-5, not 1 as you have above.
There is no detail in the PCA9959 datasheet about what the required mark-space ratio of the clock is, but I guess anything other than 50% could be a problem. You would be better to divide the clock by an even number. Either just divide 110MHz by 6 and output 18.33MHz, or else slow your core down a bit and divide by 4 (reduce the N parameter of your PLL).
Whether you use MCO or PWM don't forget to set the GPIO pin mode to the fastest slew rate available. Maybe the 8MHz you are measuring is the result of aliasing a faster clock that has been through the wrong GPIO mode. You could test this using a scope with at least 100MHz bandwidth.

Implement a virtual Instrument (MIDI OUT) on STM32, Note-On not works

I'm implementing a virtual instrument on STM32 (STM32F103x). Like a normal "hello world", I tried to start with the simplest MIDI message, sending NOTE-ON MIDI message in a loop to see if it works.
I send MIDI NOTE-ON message for every 500ms, only NOTE-ON message in a forever loop, but it not works. Is there any other MIDI message must be sent to make MIDI works? Like some initialize message?
Based on MIDI 1.0 spec, I finish my code on STM32 by sending MIDI message via USART interface.
Then use a logical analyzer, I confirmed my MIDI message is fully match the MIDI 1.0 spec. At least I believe it correct, no issue. 31250 baud rate, 1 start bit, 1 stop bit, one status message 0x92 followed by two data bytes 0x48 and 0x7F, LSB first.
Below is the NOTE-ON message captured by the logical analyzer on TX line of URAT interface. I continue send the same 3 bytes for every 500ms.
The totally time for those 3 bytes are 960 microseconds also match MIDI 1.0 spec mentioned value.
Then, based on "(CA-033) MIDI 1.0 Electrical Specification Update [2014]", I buy one 5 PIN MIDI OUT jack, connect the URAT TX line to PIN-5 through a 10 Ohm resister, connect 3.3V power to Pin-4 through a 33 Ohm resister, PIN-2 and Jack shield connect to GND. Other optional parts (buffer for Rc, ferrite beads) are not used.
However, when I use a USB-MIDI wire connect my MIDI OUT jack to my PC, nothing happen. The USB-MIDI wire has two LED indicators , one for power another for MIDI signal. After connect, the power LED is light, but the MIDI signal LED never light.
I tried to use logical analyzer to analysis PIN-5 of my MIDI OUT jack, the MIDI message byte are totally same with URAT TX line, and every 500ms one NOTE-ON message. However, it never works.
I also tried to create my own PCB with Dream SAM2695 by follow the SAM2695 Evaluation Boards. Then connect the URAT TX directly to MIDI_IN pin of SAM2695, it still no response. Since I have no confidence on my manual soldering PCB, not sure if the PCB itself has issue cause it no response. So I buy a USB-MIDI wire, but the result as I mentioned above, still no response.
======= Apr.26.2021 Update =========
Based on comments, have tried to check the output of the optocoupler.
Before do this check, I bought several BSS138 to transform the MIDI signal to 5V single use below circuit (of course change the resisters near MIDI JACK pin to 220 Ohm as the spec)
After this change I measured voltage of the 5V URAT TX, it show as 4.8+ V, and Logical Analyzer show correct MIDI note on message of this new 5V MIDI signal. However, it still not works.
The only left troubleshooting method for me is measure the output of the optocoupler on this USB-MIDI wire. But I didn't find an optocoupler on this MIDI USB wire PCB. There even do not have any one component has 4 pins on the PCB (based on my understanding, an optocoupler need at least 4 pins).
There only have one main chip on the PCB, it is possible that the optocoupler is embedded in that chip? Since the pin are too small I failed to connect my logical analyzer to those pin to check.

How to decrease wifi link quality and/or wifi signal level?

I have been following a tutorial that enables you to play around with the TXPOWER parameter of your wifi card / wifi adapter:
http://null-byte.wonderhowto.com/how-to/set-your-wi-fi-cards-tx-power-higher-than-30-dbm-0149606/
You can easily boost up your wifi range when increasing the TXPOWER.
Now, most people want to improve their wifi signal strength of their home router, right. But in my case, I would like my home router (which runs on a raspberry pi) to have a relative small wifi signal radius (say, a radius of 2 meters), so that you actually need to physically look for the pi home router when trying to connect to it.
I have learned that this tutorial does not do a thing with the wifi link quality and/or the wifi signal level and thus does not influence the wifi radius of my pi home router.
link quality & signal level
Do you guys have any ideas/thoughts about how to decrease link quality and/or wifi signal level (e.g Link Quality = 12/70 and Signal level =-10dBm) ? Is this even possible ?
I am using a Tp-Link TL-WN722N IEEE 802.11n USB - Wi-Fi Adapter.
WIRELESS LITE N ADAPTER 150M USB HIGH GAIN 1DETACHABLE ANTENNA WL-AP.
150 Mbps - External
First, I recommend reviewing this section from your link:
QUICK DECIBEL UNDERSTANDING:
Every 10 decibels is a 10X increase in power starting from 1 dBm equal
to 1mW... 10 dBm equals 10 mW, 20 dBm equals 100 mW, 30 dBm equals
1000 mW, and so on. Every 3 decibels is approximately double that of
the prior power, so 30 dBm is 1000 mW, if we add 3 dBm, then we can
double the power such that 33 dBm is about equal to 2000 mW.
It appears to me that you are able to modify the transmit power of your adapter as the tutorial states. Are you saying this is not working? If you set your transmit power to something extremely low (-30dBm, for example) you would effectively be turning off the transmitter. Keep increasing that value until you get your desired coverage radius.
If the transmit power parameter is not functioning as per the tutorial, then there are other means to achieve reduced coverage. The model you specified has a detachable antenna....so detach it. This would definitely reduce your coverage. However, if it reduces coverage too much, you could simply add an inline attenuator. Fortunately, your antenna uses an SMA connector which is very common. You can find many SMA attenuators on ebay with different attenuation values. Experiment with different values until you get the desired coverage.
And if that doesn't work, just wrap a bunch of aluminum foil around the thing lol.

NodeMCU ESP8266 I2C Module High-Speed

I am making a wireless device to measure a magnetic field based on the HMC5983 magneto-resistive sensor and an ESP8266 (NodeMCU ESP-12e module).
The sensor is connected to the ESP8266 on the I2C interface. The
ESP8266 polls the sensor and sends this to a data collector (Raspberry Pi).
It is extremely important to me to achieve the greatest possible number of computation in a second, as quality of the obtained data for later processing depends on it.
HMC5983 supports the I2C interface in Standard, Fast and High-speed modes. But the NodeMCU I2C Module only supports i2c.SLOW speed.
common I²C bus speeds are the 100 kbit/s standard mode and the 10
kbit/s low-speed mode https://en.wikipedia.org/wiki/I%C2%B2C
Then I connected the HMC5983 directly to the Raspberry Pi via I2C. I could achieve about 500 measurements per second (by monitoring the DRDY interrupt pin) in single-measurement mode and 200 measurements per second in continous-measurement mode (with Data Output Rate at 220 Hz - all right).
The programm was written in Python, here is the code:
#!/usr/bin/python
import smbus #for i2c use
import time
import os
bus = smbus.SMBus(1) #use i2c port 1 on Rasspberry Pi
addr = 0x1e #address HMC5983 0x1E
bus.write_byte_data(addr,0x00,0b00011100) #Write to CRA Speed 220Hz
bus.write_byte_data(addr,0x01,0b00100000) #Write to CRB Gain 660 +-2.5Ga 1.52mG/Lsb
print "Start measuring.....
while True: #if we need infinity cycle
bus.write_byte_data(addr,0x02,0b00000001) #Write to Mode single-measurement mode
while bus.read_byte_data(addr,0x09) == 0b11: #Wait RDY in Status Register
()
#DATA READY
data = bus.read_i2c_block_data(addr,0x03,6)#Take data from data registers
#convert three 16-bit 2`s compliment hex value to dec values and assign x,y,z
x = data[0]*256+data[1]
if x > 32767 :
x -= 65536
y = data[2]*256+data[3]
if y > 32767 :
y -= 65536
z = data[4]*256+data[5]
if z > 32767 :
z -= 65536
print "X=",x, "\tY=",y, "\tZ=",z
When I connected the HMC5983 to the ESP8266, I could achieve only about 140 computations a second in single-computation mode.
----------THIS IS FOR SINGLE-MEASUREMENT MODE-------------
--init i2c
function H_init(sda,scl)
i2c.setup(id, sda, scl, i2c.SLOW)
print("I2C started...")
end
-- reads 6byte from the sensor
function read_axis()
i2c.start(id)
i2c.address(id, dev_addr, i2c.RECEIVER)
data = i2c.read(id, 6)
i2c.stop(id)
return data
end
--set register
function set_reg(reg_addr,val)
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id,reg_addr)
i2c.write(id,val)
i2c.stop(id)
end
--------GPIO INITILIZATION-------
drdyn_pin=3
gpio.mode(drdyn_pin, gpio.INPUT)
-------I2C INITILIZATION-------
id = 0
i2c = i2c
local i=0
dev_addr = 0x1e
H_init(1,2)
set_reg(0x00,0x1c) --set speed 220Hz
set_reg(0x01,0x20) --set gain
print("Start measurement...")
while true do
set_reg(0x02,0x01) --single-measurement mode
while(gpio.read(drdyn_pin) == 1) do
end
data = read_axis()
tmr.wdclr()
end
After that I configured the sensor to continous-measurement mode and received the same 200 measurements per second.
Is operation of the I2C interface in NodeMCU at high speeds possible? Can somebody tell me how to try to accelerate sensor polling?
Of course it is possible, ESP8266 is faster than Pentium :-) Just a few thousands or even just a few ten thousands measurements per second would be really disappointing for such tremendous processing power. Here you are the link to ESP8266 I2C library written in assembly and tested with Arduino toolchain. That way you can communicate at the rate of 800000 messages per second #80 MHz or one million messages per second #160 MHz. I believe that would be more than enough for the project you have described, at 80 kHz I2C speed you can have a few ten thousands measurements per second - if a slave device can handle such speed.
For any future doubts if something could or couldn't be done with ESP8266, I'd say this is more than enough to get a picture - and in this case I mean it literally :-)