PSoC5lp ADC and I2C slave (reading duplicate values)

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
mwors7
Level 2
Level 2
10 replies posted 10 sign-ins 5 replies posted

Dear community,

This post is quite similar to one I previously posted (sorry for that) however I am more interested in how the PSoC5lp I2C slave works under the API functions.

Currently I have a raspberry pi I2C master reading 16-bit ADC data from a PSoC5lp (CY8KIT-059). I have set the ADC conversion rate to 2000 samples/second and the I2C bus frequency to 400 bits/second. Thus, for only one slave, the I2C bus is running more than fast enough to read the 2000 samples/second in time and I believe this is fine. My issue is that I believe the raspberry pi master is coming back to the PSoC5lp I2C slave before I2C slave buffer has had time to update to the next ADC sample. See I2C_data_duplicates.jpg attachment (it looks like a valid EMG signal which is what the ADC is sampling), however the signal is over sampled (I am tensing my bicep for 3 seconds and thus there should be approximately 6000 samples in each burst). I2C_data_duplicates_zoom.jpg shows that for each sample there are around 3 or 4 consecutive duplicate samples with approx. 25000 samples in a burst. Thus, post-processing I decided to write some code to remove consecutive duplicates (I2C_data_no_duplicates.jpg/ I2C_data_no_duplicates_zoom.jpg). When removing the duplicates, the approx. number of samples in a burst reduces to 6581 (which when divided by 3 seconds) is about 2193.67 samples/second. Removing duplicates, the sample rate is close to what is set in PSoC creator. Removing duplicates is not a robust solution of course - as sometimes a duplicate sample might actually be correct.

So my question is - the way that PSoC sets up the I2C slave component, is it possible for the Rpi master to read data multiple times from the same slave buffer before it is updated? In most code examples I see the comment "Read complete- expose buffer to master" when they perform this code:

/* Read complete: expose buffer to master */
if (0u != (I2CS_I2CSlaveStatus() & I2CS_I2C_SSTAT_RD_CMPLT))
{
/* Clear the slave read buffer and status */
I2CS_I2CSlaveClearReadBuf();
(void) I2CS_I2CSlaveClearReadStatus();
}

So I thought if I updated the slave buffer and then called this it should be fine.

Any advice is greatly appreciated.

Cheers,

mwors7

0 Likes
4 Replies
Raj_C
Moderator
Moderator
Moderator
250 solutions authored 500 replies posted 50 likes received

Hi @mwors7,

 

You can copy the data from the ADC buffer to the I2C buffer and once it is filled you can initiate master to read it completely and after that empty the slave buffer. Don’t read and write simultaneously.

After the complete read of the given buffer size, stop the communication or you can implement a buffer on the master side to check if the data is being read. If the read is successful then stop reading the slave buffer.

I recommend you to go through PSoC 5 LP code examples for DelSig_I2CS and EZI2C.

If possible can you please, attach the updated project file here or let me know if it is still the same as in the previous post. I will look into it and try to implement it on my side. 

 

Thank you

Best Regards

Raj Chaudhari

lock attach
Attachments are accessible only for community members.
mwors7
Level 2
Level 2
10 replies posted 10 sign-ins 5 replies posted

Hi @Raj_C ,

Thank you for getting back to me again. I have been through many code examples for DelSig_I2CS and EZI2C and from my understanding I have done everything correctly.


Can you please tell me how to stop communication briefly after complete read of I2C slave buffer? I think that is what I need to do. I do not want to stop communication completely however, as this data will be sending continuously, I just want to halt the communication until the slave buffer has been updated with the next ADC data from the circular buffer.

I am attaching my project file - it is more or less the same as it was before - but I have cleaned it up for readability and explaining the logic in my processes. Please let me know if you find any mistakes or if you manage to get it working. I will also attach the master code I have on my Raspberry pi side in the next post.

Thank you very much,

Best Regards

Matthew Worsey

0 Likes
mwors7
Level 2
Level 2
10 replies posted 10 sign-ins 5 replies posted

Hi @Raj_C 

Please find the code on the Raspberry pi side (master) below, I use the SMbus2 module for I2C communication.

########################################################

#Script for saving ADC data received over I2C to txt file on SD card
#By Matthew Worsey - 9th Dec 2021
#Updated for readability in forum (13th Jan 2022)

#Import required libraries
from time import sleep
import pandas as pd

#Import the system bus library for using I2C
from smbus2 import SMBus, i2c_msg
import time

#Define I2C communication functions

######################################

I2CS_ReadBytes

######################################
# Definition: Read (N) bytes of data from non-register basedI2C slave device (addr) (PSoC5lp)
# Inputs: N - number of bytes to be read from slave buffer, addr - slave address of device
# Outputs: Data_full - The full data from the slave with bit manipulation applied
###########################################################################################
def I2CS_ReadBytes(addr,N):
msg = i2c_msg.read(addr,N)
bus.i2c_rdwr(msg)
data = list(msg)
# If the number of bytes read does not match intended then throw an error
if(len(data) !=N):
print('Error- byte mismatch')
#Bit shift data from int8 to int16
data_full = data[0]*256 + data[1]
return(data_full)
###########################################################################################

#Open I2C bus 1
bus = SMBus(1)

#Set the slave address of PSoCs
slv0_addr = 0x66

#Set the number of bytes to be read from the slave devices
nBytes = 2

#initialise sample number
sn = 1

#Start forever while loop
print("Press Ctrl-C to terminate while loop and data logging")
try:
while True:
samples = [] #Declare a tuple variable
#Run through 5000 bytes and then write to file
for i in range(5000):
data_full_0 = I2CS_ReadBytes(slv0_addr,nBytes) # Read 2 bytes from PSoC5lp slave
samples.append((sn, data_full_0)) #append the latest ADC data read on I2C bus and corresponding sample number
sn = sn+1 # Increment the sample number

name = ['Sample_number', 'EMG0']
f = pd.DataFrame(columns = name, data = samples)
#Write to file
f.to_csv('/home/pi/Documents/I2C_scripts/Smbus2/EMG_I2C/CSV_exports/Data_Fs_test_2k_i2c_400_13.csv',mode = 'a',float_format = '%.2f',header = False, index = 0)

#Enable user to exit while loop on a keyboard interrupt
except KeyboardInterrupt:
pass
bus.close()

Cheers,

Best Regards

Matthew Worsey

0 Likes
mwors7
Level 2
Level 2
10 replies posted 10 sign-ins 5 replies posted

@Raj_C

Hi Raj, did you have any luck on your end?

 

Cheers, 

 

Matthew Worsey 

 

0 Likes