Esp32 Micropython Max31865 Spi connection and data read - esp32

I need to read temperature data with using MAX31865 SPI communication. First of all, I tried to read 4 byte data:
import machine
import ubinascii
spi = machine.SPI(1, baudrate=5000000, polarity=0, phase=0)
#baudrate controls the speed of the clock line in hertz.
#polarity controls the polarity of the clock line, i.e. if it's idle at a low or high level.
#phase controls the phase of the clock line, i.e. when data is read and written during a clock cycle
cs = machine.Pin(15, machine.Pin.OUT)
cs.off()
cs.on()
data = spi.read(4)
cs.off()
print(ubinascii.hexlify(data))
I tried many times with different codes but result is always similar b'00000000'.
I am using ESP32 WROOM.
I used this pins:
ESP32 : D12 - D14 - 3V3 - GND - D15
Max31865: SDO - CLK - VIN - GND - CS
I am new on micropython and esp32.
I don't know what should I do. Is there any suggestions , recommended tutorials or idea?

Short answer: see if you can use CircuitPython and its drivers for MAX31865.
Long answer: a bunch of stuff. I suspect you've been following the Adafruit tutorial for MAX31855, but its SPI interface is very different from the MAX31865.
Your SPI connection is missing the SDI pin. You have to connect it, as communication is bidirectional. Also, I suggest using the default SPI pinout on ESP32 side as described in the micropython documetation for ESP32.
The SPI startup looks to be missing stuff. Looking at the SPI documentation a call to machine.SPI() requires that you assign values to arguments sck, mosi, miso. Those would probably be the pins on ESP32 side where you've connected SCLK, SDI, SDO on MAX31865 (note mosi means "master out, slave in" and miso is "master in, slave out").
The chip select signal on the MAX is inverted (that's what the line above CS input in the datasheet means). You have to set it low to activate the chip and high to disable it.
You can't just read data out of the chip, it has a protocol you must follow. First you have to request a temperature-to-resistance conversion from the chip. The datasheet for your chip explains how to do that, the relevant info starts on page 13 (it's a bit difficult to read for a beginner, but try anyway as it's the authoritative source of information for this chip). On a high level, it works like this:
Write to Configuration register a value which initiates the conversion.
Wait for the conversion to complete.
Read from the RTD (Resistance-To-Digital) registers to get the conversion result.
Calculate the temperature value from the conversion result.
The code might be closer to this (not tested, and very likely to not work off the bat - but it should convey the idea):
import ubinascii, time
from machine import Pin, SPI
cs = Pin(15, Pin.OUT)
# Assuming you've rewired according to default SPI pinout
spi = machine.SPI(1, baudrate=100000, polarity=0, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12))
# Enable chip
cs.off()
# Prime a 1-shot read by writing 0x40 to Configration register 0x00
spi.write(b'\x00\x40')
# Wait for conversion to complete (up to 66 ms)
time.sleep_ms(100)
# Select the RTD MSBs register (0x01) and read 1 byte from it
spi.write(b'\x01')
msb = spi.read(1)
# Select the RTD LSBs register (0x02) and read 1 byte from it
spi.write(b'\x02')
lsb = spi.read(1)
# Disable chip
cs.on()
# Join the 2 bytes
result = msb * 256 + lsb
print(ubinascii.hexlify(result))
Convert result to temperature according to section "Converting RTD Data Register
Values to Temperature" in datasheet.
Side note 1: here spi = machine.SPI(1, baudrate=5000000, polarity=0, phase=0) you've configured a baud rate of 5MHz which is the maximum for this chip. Depending on how you've connected your devices, it may not work. The SPI protocol is synchronous and driven by master device, so you can set any baud rate you want. Start with a much, much lower value, maybe 100KHz or so. Increase this after you've figured out how to talk to the chip.
Side note 2: if you want your conversion result faster than the 100ms sleep in my code, connect the DRDY line from MAX to ESP32 and wait for it to go low. This means the conversion is finished and you can read out the result immediately.

Related

SPI write operation ends earlier than expected

I have a problem using the SPI bus user space driver (spidev) in version 4.14 of lnx-xlnx. Sometimes only one byte (instead of for example the desired 4 bytes) is written to the MOSI due to SCLK dropping, for no apparent reason in a full duplex transfer. What could be happening?

Arduino Serial transmitting Missing One Charcter

I am using Arduino Leonardo to transmit an string to a wifi module. The format of command that wifi module can recognize is:
AT60,1,content to a server
I am using an virtual server(TCP/IP Builder) to test the content I can received.
Here is the content I want to send:
smart/device/deviceCmd?userId=1010002003&deviceId=A00019999990002&cmd=ON
Since I try to send it again and again, I use a loop to send it. In the virtual server side, the content I got is:
smart/device/deviceCmd?userId=1010002003&devceId=A00019999990002&cmd=ON
smart/device/deviceCmd?userId=1010002003&devceId=A00019999990002&cmd=ON
smart/device/deviceCmd?userId=1010002003&dviceId=A00019999990002&cmd=ON
smart/device/deviceCmd?userId=1010002003&eviceId=A00019999990002&cmd=ON
smart/device/deviceCmd?userId=1010002003&devieId=A00019999990002&cmd=ON
smart/device/deviceCmd?userId=1010002003deviceId=A00019999990002&cmd=ON
smart/device/deviceCmd?userId=1010002003&dviceId=A00019999990002&cmd=ON
smart/device/deviceCmd?userId=1010002003&dviceId=A00019999990002&cmd=ON
smart/device/deviceCmd?userId=1010002003&deiceId=A00019999990002&cmd=ON
smart/device/deviceCmd?userId=1010002003&dviceId=A00019999990002&cmd=ON
This is the QUESTION: There exist one terrible mistake in the content I received, which is the deviceId part never correct. It's so weird.
Here is part of related code:
//In Uart.cpp
//These three lines can sent a formatted string as "AT60,1,content"
Serial1.write("AT60,");
Serial1.write(channelID); //channel ID = 1 here
Serial1.write(reportIsFire, 76);
//In Uart.h
//Definition of the string I need to send, which has 76 characters.
char reportIsFire[76] = ",smart/device/deviceCmd?userId=1010002003&deviceId=A00019999990002&cmd=ON \n";
Here is few background of this application:
I am using Arduino 1.5.8 IDE with VisualStudio
Since the serial buffer of Arduino is only 64 Bytes, I have already
change the buffer size to 128 Bytes in "HardwareSerial.h" to send
out this large string.
The baud rate is 115200 and I am using Serial 1. I have used Serial 1
to transmit few other characters and it works fine.
I will appreciate that If you have any idea about this question.
I am betting that the serial baud rate of the Arduino is not 100% correct. Increasing the buffer size will not matter if the data is being lost due to a timing issue in the physical link.
I'd recommend double-checking the code that initializes the serial baud rate generator. It may be possible to get a closer rate to 115,200 by either adjusting the available settings, altering the main clock speed (if possible), implementing some form of flow control, or all of the above.
In extreme cases, you may consider using a special-frequency oscillator. Many Microchip PICs use an internal or external 4MHz or 8MHz crystal, but this can produce far too much timing error for lengthy serial transmissions at high speed. In that case, something special, like a 7.3728MHz crystal can be used, bringing the accuracy to exactly 100% (at least on some PIC devices.)
Lastly, another consideration is if any pre-emptive code is running on the device, such as interrupts or timers which could inadvertently interfere with the serial output.
I don't have an answer, but I suspect the most likely problem is that the Wifi card can't read characters at a sustained 115200 baud rate. If possible, set the Wifi baud rate and the Arduino Serial.begin() to a lower rate, such as 57600 or 19200.
If the Arduino baud rate was simply inaccurate, I'd expect to see the problem appearing at random locations in the string, rather than about 40 characters in.

Is it possible to query serial port tx pin status (signal low / high) in windows?

Is it possible to query serial port tx (send) pin status if it is active or not ?
For example when issuin break command (SetCommBreak) tx pin is set to active (low). I'd like to know when it is active or not. Thanks.
No. (at least not likely)
If you are using the "16550" family of UARTs, then I am confident that you can not query the serial port tx pin status. Of course, if you are using some new version or other UART family, maybe.
You can assume that the TX pin is in the SPACE state ('0', +Volts) whilst performing SetCommBreak(), but I suspect that is not enough for you.
If you are look to debug your code to know if a break occurred, you can short pins 2 & 3 on a 9-pin D-sub, thus loop backing the transmit to the receive. A paper clip will do. Your receive code would detect the incoming BREAK. Shorting to the incorrect pin does not cause a lasting problem with a conforming serial port, but be careful. Try this first with simple data, before testing BREAK condition.
If you have a "16550"-like UART.
You can put the UART into loop-back mode and see if you receiving you own outgoing BREAK signal. Its somewhat complicated in current PCs. Other UART type may support loop-back.

CAN Bus Protocol Implementation

I want to learn and implement CAN BUS protocol. I have implemented UART,SPI,I2C and One Wire Bus protocol using MSP430 Launchpad in software. Now I want to learn about CAN Bus protocol. I have mBed LPC 1768 Cortex M3 Development board. mBed has Can Bus Library but I want to write my own library so that I can learn it in detail, i.e. the way I did for other communication protocols.
I am not able to find suitable resources to start with and the material appears to be scattered on net. Can any one guide how do i write and implement CAN Bus protocol with the development boards available with me.
Thanks
Developing CAN library is relatively easy as compared to I2C or SPI. This is because CAN Controller of your Cortex will take care of most of complex things.
To transmit the data, You have to write ID and Data in designated registers and set bit to transmit data.
This Application note from NXP can be very useful for you.
I would recommend you to implement following functions:
InitCAN - This should set specified Baud Rate of CAN.
SetFilters - Most CAN Controllers come with Acceptance Filters, So it's good to have that
SendData - Make sure you accept Parameters like ID_Type and RTRs etc.
RecieveData - This can be blocking or Interrupt based.
Before beginning, do read CAN Basics to understand. Application notes AN713 and AN754 from Microchip is a good source. Also Vector's site and Wikipedia Article.
Plus, You can always post your doubts here or on Electronics.StackExchange.com :)
Okay so this post is quite old but people may look at it again so:
First of all Can bus is not user friendly protocol like USART or IC2 at all so you have to be very precise about your can bit timing there are tools for that but I suggest you to calculate them by hand. For a microcontroller I would suggest STM32 and be away from PIC series in my opinion. If it's only CAN-BUS without higher level protocols such as SAE J1939, steps are pretty simple and straight forward:
1)Initialize Can
2)Put CAN to configuration mode and remember that you can set baudrate, mask and filters only in configuration mode!
3) Set the baud rate registers.
4) Set the mask and filters. If you need to receive all messages just simply set mask to 0x00. Then filter will be do not care.
5) Set the CAN to the normal or loopback mode. (loopback mode is used for debugging purposes mostly.)
Some remarkable points people try to implement can at the beginning may miss:
*** You need at least 2 working CAN nodes for successfull transmission. (of course with matching baud rate). So if you want to send some data via CAN with 1 node it will not be succesfull. Because your transmitter node will not receive ACK.
*** Most likely you will need a CAN tranciever. Do not forget to put a 100 ohm or similar value resistor between Tx and Rx pins of your tranciever.
I used the software canking to talk to a mcp25050 when I learned how to implement can protocol using an hcs12 dragonboard. It helped a lot because canking will initialize everything for you when u go on the bus and all you have to do is learn how to write and recieve. If you want to learn how to initialize the steps are:
Enables can bus by setting bit on CAN Control Register 1
Enable can initialization Control Register 0
wait until can bus is in initialization mode by checking control register 1 bit
Enables can bus by setting bit on CAN Control Register 1 again and set clock source - Ethier bus clock or eclock
set prescaler baudrate and Tq with Bus timing register
set sample time and prop_seg1, prop_seg2, and phase_seg
set acceptance id on Identifier acceptance register 0-3 or 0-7 - to set your can to recieve everything set those to 00 because when doing a compare the can bus does a ones complement compare with the id coming in
set Identifier mask register 0-3 or 0-7, if you want to not care about any of the bits set them all to FF
set identifier acceptance control register to 32 bit extended or 11 bit - i use 32
set Control Register 0 back to normal mode
wait until bus is normal mode by checking Control Register 1
after this you can start changing registers or reading data to do this you must select the empty can buffer, write your id to write or request data, and then input the address, mask, and value in the 3 transmitter registers if writing and then specify the dlc (3 if writing and 8-1 if reading). to transmit the id and data you then have to set the can transmit flag to equal the can Transmit buffer selection.
** depending on what id you use bit shifting can be tedious so if you are having a problem I would suggest debugging and looking at what your Transmit buffer selection registers are holding. I had this error because i did not shift correctly when i was sending messages to the mcp25050
If your MCU supports CAN Bus, you should start from the related datasheet.

Writing to Micro SD from SHARC 21469 idle and speed issues.

I can properly read/write to a 2GB Kingston Micro SD using single pin SPI, but after writing using the WRITE_MULTIPLE_BLOCK command to write several blocks, the card goes into idle mode. I know this because when I try send a command to write more data, the card returns an 'in idle state' flag. I created a work around that pulls the card from idle after each write but this severely reduces the bandwidth. Does anyone know why this happens?
Also, the maximum SPI Baud I have obtained is 1Mbs. When I set the SPI clk to >1MHz the commands do not work properly. If I send commands at a baud of < 1Mbs then send the data at >1Mbs, the data is corrupted. Is there a reason I have not been able to get the 25MHz specification speed as listed in the SDCARD.org spec on p2?
https://www.sdcard.org/developers/tech/sdio/sdio_spec/Simplified_SDIO_Card_Spec.pdf
I got SPI Speeds less than 1 MBit/s when I tried to use the wrong SPI clock polarity once. Double check this, and this is also a possible candidate as a source for you "idle" error.

Resources