Shop OBEX P1 Docs P2 Docs Learn Events
Propeller Activity Board for I2C interface "Line follow sensor" question — Parallax Forums

Propeller Activity Board for I2C interface "Line follow sensor" question

王柏鈞王柏鈞 Posts: 21
edited 2016-03-14 07:08 in General Discussion
Hello everyone, I am a university student from TW
I want to using propeller Activity Board to follow the Line
I use SimpleIDE to writing my project
But I'm not really understand how to read I2C sensor
////////////////////////this is my code////////////////////////////////////////////////////
#include "i2ceasy.h"
#include "simplei2c.h"
#include <math.h>
int x=0;
int main()
{

while (1)
{
i2c__init(3, 2); // SCL pin, SDA pin
x=i2c__read(0x3E);
print("x = %d\n", x);
pause(500);
}
}
////////////////////////this is my code////////////////////////////////////////////////////
And I using the sparkfun line follower array
I think it have singel to my board,but it can't read the sensor detect
can someone help me?
«1

Comments

  • Perhaps you should go through the I2C portion of Simple Protocols Tutorial to more fully understand how it works in Simpleide.
    http://learn.parallax.com/propeller-c-simple-protocols/diy-i2c
  • Thanks Hal Albach
    But it is hardware tutorial , I want to know about how to work with software.

    And in that web , it say I can use "ee_putByte, ee_getByte, ee_putInt, ee_getInt, ee_putFloat32, ee_getFloat32, ee_putStr, and ee_getStr." to quick way saved data .Can I using that to saved my sensor data?
  • Did you go through all 4 pages which show how to set up the I2C functions? It's not just all hardware. The "ee_....." functions you listed are used specifically for the eeprom connected to the propeller. You cannot use these to access a different device.
    To get to the next page look at the bottom of the page I linked to you. You will see what I show below between 3 horizontal lines:
    
     
    
               EEPROM Test Code
               Did You Know?
               More Data Types and Devices
    
    
    ‹ Bit Masks for Better Code
    
                                                            up
    
                                                                                 EEPROM Test Code ›
    
    Bottom right is the link to the next page. Click on "EEPROM Test Code" and you will see a whole page on how to use the I2C library function. There will be two more pages after that.

  • 王柏鈞王柏鈞 Posts: 21
    edited 2016-03-15 01:19
    Hal Albach,
    I see that , I think that is helpful,but I have some question for it.
    Isn't "i2cAddr" sensor address? or the 0b1010000 just the EEPROM's address? It seen like just the EEPROM's address.
    If I want to add my sensor,is that code right?
    "i2c_in(eeSensor, 0x3E, memAddr, 2, (char*)&val, 8 );"
    "eeSensor"is a new I2C bus name,"0x3E"is my sensor I2C address.
  • Carefully reread the explanation for i2cAddr and you will see that it is a 7 bit address, not an 8 bit. It is better you use the bit format like in the example. 0x3E = 0b00111110, per the example drop the right most bit and the i2cAddr should be 0b0011111 (remember, 7 bits only.
    memAddr is the device's internal address followed by how many bytes memAddr is long. You put 2 after memAddr, meaning that memAddr is 16 bits wide. Does your device have that many internal addressable locations? I2C expander chips do not. You probably want to use 1.
    (char*&val,8); is something that you copied from the example in the last page dealing with reconstructing a 16-bit word from two 8-bit bytes from an eeprom. Don't do that! Instead, use the array name you have established to point to the data byte(s) to store the data that was read from the device, followed by how many bytes you want to read.
    i2c_in(eeSensor, 0b0011111, memaddr, 1, inByte, 2);
    
    inByte should be a char array, for example;
    char inByte[2];
    
    To properly read the I2C bus with a specific device on that bus is going to require you to dig into the device data sheet and find out what the internal addresses are. I encourage you to try the tutorials on your Propeller Activity board and get comfortable with the way the I2C Library works. I use it with many devices such as RTC, expanders, EEPROM, etc.
  • Thank so much, Hal Albach , but I had one more question fot it.
    "memaddr" is my sensor memory address,right ? But I don't know my sensor memory address.
    I read "Did you know?" page , but English is not mine native language , so I can't really understand what it mean.
    I just know Propeller board's EEPROM addresses is 0 to 32767,how did that know?
    I'm so sorry about asking you so many idiot questions.
  • https://www.sparkfun.com/products/13582
    Is this the device you are trying to use?
  • Hal Albach,
    yes, I try for this sensor.
    And I look the datasheet for SX1509, It say "0x3E" should be "0111110" , not "0011111",isn't it?
    I found a library for propeller , it's name "i2ceasy.h",did you use it before?
  • When setting up a 7 bit address you have to consider how the I2C Master is handling the device address. In the Simpleide I2C that I linked the tutorial for, the I2C master will take the 7 bit address, shift it left once and append the appropriate LSB (bit), 0 for write, 1 for read. In a program I am using I have added an EEPROM which has an address of 0xAE or 0b10101110. In order for the address to work with this I2C the 8-bit address has to be right-shifted once, becoming 0x57 or 01010111, in 7-bit it becomes 0b1010111. In a 7-bit or 8-bit address, the rightmost bit remains bit 0.
    For someone who has very little knowledge with I2C programming, learning with an SX1509 will be a very difficult task.
    I am not familiar with 12ceasy.h, cannot help you with that.
  • Hello Hal Albach,
    I know 0 for write,1 for read,but I don't know how to put it in program.
    /////////////////////////////////////////////////////////////////////////////////////////////
    #include "simpletools.h" // Include simpletools header
    int x;
    char inByte[2];
    i2c *eeSensor;
    int memAddr = 32768;
    int main() // Main function
    {
    while(1)
    {
    eeSensor = i2c_newbus(4,3,0);
    i2c_in(eeSensor, 0b1111100, memAddr, 1, inByte, 2);
    print("val = %d \n",inByte);
    pause(500);
    }
    }
    /////////////////////////////////////////////////////////////////////////////////////////////
    It will running for inByte=9527, can you help me to modify it?
    I think my memAddr is the problem for it , isn't it?
    or should I use "EEPROM" for reading the "inByte"?
  • Good evening!
    Several problems with your code;
    The statement "eeSensor = i2c_newbus(4,3,0);" should be placed before the while(1) loop. You don't want to constantly run the newbus statement hundreds or thousands of times. Once will do it until you close the bus.
    Next is the device address. Remember, this I2C library will take your 7-bit address and shift it left once. The address you have given has a 1 bit in the left -most position which will be lost - not a good thing! Another way of converting an 8-bit I2C address to 7-bit is to simply divide it by two. 0x3E / 2 = 0x1F or b00011111. Now, starting from the right, or LSB position, count off 7 bits and you should have 0b0011111.
    Do not concern yourself with the read/write bit. The library will take care of that. After it shifts the 7-bit address left once it will insert the proper bit into the LSB position, depending on the operation.
    memAddr This parameter is telling the I2C library the location (or address) of the register or memory byte that is inside the slave device. This is where you have to look at the datasheet for the address of the location you want to read. You have indicated a memAddr of 32768. You probably got this number from the tutorial that was accessing the 2nd half of a 64KB EEPROM. Again, the information is in the datasheet. The number following memAddr is the number of 8-bit bytes that memAddr is made up of. If your device has 255 or less locations memAddr will be 1 byte. If the highest address is between 256 and 65565 then memAddr will have 2 bytes, and so on.
    It looks like you are making some progress. Just remember to refer to the device data sheet for the addresses of the locations you want to read. In most cases, when a device has multiple addresses it will auto-increment its location pointer so that the next read or write command will read or write the next location.
  • Hal Albach,
    Why can I2C address divide by two? When I divide it by two , the address will be 0x1F, can it find the right address?
    I put "eeSensor = i2c_newbus(4,3,0);" before "while(1)"(I am so idiot for put it in while) , inByte will be "9520".It look like it doesn't read the sensor.
    So the memAddr is the memory byte of the register?I just wanting to read 255 to my device, so the memAddr will be 1 byte,right?
    Yes,I am making some progress for robot race, it can use I/O pin for other sensor to do that,but that race should need colorPal、Ultrasound and line following sensor, so I want to try the I2C sensor for not using so many I/O pin.
  • Hal AlbachHal Albach Posts: 747
    edited 2016-03-23 04:35
    It may be that the 3E address provided by the data sheet is the 7-bit address, in which case you might use 0b0111110 as the device address, as you had mentioned earlier. I had thought it represented an 8-bit address.
    In the SX1509 data sheet on pages 30 - 35 is the listing and description of the device internal registers. The highest address is 0x7F so memAddr should never be greater than 0x7F.
    Which location are you trying to read?
    If, for example, you wish to read location 0x0F ( RegDirA) then your code might look like the following:
    char inByte[2];                   // receive buffer array
    i2c *eeSensor;
    #define devAddr   0b0111110       // SX1509 device address
    int memAddr = 0x0F;               // SX1509 register address
    int main()                        // Main function
    {
      eeSensor = i2c_newbus(4, 3, 0);
      while(1)
      {
        i2c_in(eeSensor, devAddr, memAddr, 1, inByte, 1);
        print("val = %d \n", inByte);
        pause(500);
      }
    }
    
    This should result in a display of 255 repeating 2 times per second.
  • Hal Albach,
    I try this code and change the SX1509 register address for other address,but it still return inByte=9720.
    Should I use other I2C sensor to text it work or not?
    I was finding some data for I2C , but not find useful data for this progress.
  • Can you post the code you compiled and loaded? Do you have the pull up resistors on the two I2C lines?
  • 王柏鈞王柏鈞 Posts: 21
    edited 2016-03-22 01:38
    Hal Albach,
    The code is like the code you post.
    I don't pull up resistors because when I pull 1k resistor it will not enough to work(I put it for the VIN),and I try put 1k and 220 resistor for two I2C line, it still return 9720.
  • I looked at the Sparkfun board and it has the pull up resistors on the board. Can you tell me how you have the two boards wired together, each wire where it connects to on the boards? I am wondering if you are powering the Sparkfun board with 3.3 or 5 Volts.
    The only item in the code I did not include is the line
    #include "simpletools.h"
    
    but you would get compiler errors if that was missing.
    Do you have other types of I2C devices like an EEPROM that you can try to make sure the code is working?
  • Hal Albach,
    I was include that library on the top,so it wasn't errors for compiler.
    The powering I was use 5 Volts for board.
    I was using for arduino before,but I don't use any resistors and it can work.
    Sensor board
    5v->5v
    GND->GND
    SDA->P3
    SCL->P4
    All without any resistors
  • When you were using the Sparkfun board on the Arduino were you able to establish I2C communications? If you did, can you hook the board back up to the Arduin and see if it still works? Also, did you modify the board in any way for the Arduino such as cutting or removing jumpers or adding jumpers?
    Do you have a Voltmeter to verify that P3 and P4 are at 3.3 Volts? It is best that you remark out the i2c_in... statement so there is no activity on the bus.
  • 王柏鈞王柏鈞 Posts: 21
    edited 2016-03-22 03:50
    Hal Albach,
    I was able to establish I2C communications for Sparkfun board on the Arduino,but the Sparkfun company have provide a library for this sensor,it let this sensor easy to ues for Arduino.
    And I try the example, it can work on Arduino.
    P3 and P4 are at 1.2Volts,but I see everyone put the I2C pin for P2 and P3 can work, I also try this is,but it's the same promble.
  • Hal AlbachHal Albach Posts: 747
    edited 2016-03-22 12:30
    Do you have any other I2C slave device besides the SX1509 that you can try?

    Several posts up your reply to the code I provided was;
    "I try this code and change the SX1509 register address for other address,but it still return inByte=9720."
    What did you change the SX1509 register address to?
  • Hal Albach,
    I don't have any other I2C slave device besides the SX1509.
    I change the register address in the code "0x0F" for the other address on page 30~35.Not change the SX1509 register address.
  • Hal AlbachHal Albach Posts: 747
    edited 2016-03-23 00:30
    When you took those voltage readings on P3 & P4, did you disable the i2c_in.... statement? 1.2 volts seems a little low even if the bus was active. I'm just trying to make sure that the bus is properly pulled up and not just left floating. With that one half second delay between readings the meter should be showing much closer to 3 Volts or slightly more. If you would, can you disable the i2c_in... statement and take another voltage reading on P3 & P4?
  • Hal Albach,
    I was reading the i2c_in statement before,but I see some people use P3&P2 for i2c_in in their progress.So I think it is fine to use P3&P4.
    And I test the arduino A4&A5 for I2C ping, it is 4.5v,I think maybe is the voltage promble.
    You say "With that one half second delay between readings the meter should be show a much closer to 3 Volts or slightly more" , what's it mean?Isn't change delay to delay(250) or lower?
  • "You say "With that one half second delay between readings the meter should be show a much closer to 3 Volts or slightly more" , what's it mean?Isn't change delay to delay(250) or lower? "

    What I am referring to is the I2C bus for the propeller must be pulled up to 3.3 volts. Active devices on the bus pull the lines to zero volts during data transfer. The devices only pull down, the pull up resistors are required so that when the device stops pulling the line down the voltage on that line goes back to 3.3 volts.
    My concern here is that you have used this Sparkfun board on an Arduino, which runs on 5 volts. The Sparkfun board has several jumpers on it that let you set the pull up to none, 3.3 Volts, or 5 Volts. If it is set to none and you now try to run it on the Propeller Activity board without any pull up resistors, the I2C will not work.
    My reference to the half second delay was just me thinking out loud that even if you did not disable the i2c_in... statement the amount of activity on the bus is quite low and as a result your meter should see a voltage much closer to 3.3 Volts. The 1.2 Volt reading you gave me earlier is less than half the voltage the propeller runs on.
    I'm just trying to get you to provide a clean, quiet bus voltage reading to make sure that it is being pulled up to 3.3 volts. If you are not sure on how to disable that statement, just place // in front of it to make it a comment. Then compile and download the program, and then check the voltage.
  • Hal Albach,
    I'm so sorry for that,I change a voltmeter and I detect again P3 and P4, the voltages is almost closer 3.3v. And it also return 9720 for me.So it is not the voltages promble.
  • OK, let us try something very different. What I would like to do is use the example DIY I2C program and see if that works. I will give you the link again and go to the EEPROM Test Code page and follow the instructions there to load the program from your Learn\Examples library. This is to make sure that your library code is working. Just load the program without making any changes. What it will do is write a small string of characters to the upper half of the EEPROM that is on the Activity Board and then read that same location from EEPROM and display it on your screen. Just remember to use the blue "Run with Terminal" button to compile and run the program. If it works the screen should show
    testStr = abcdefg
    
    Let us see what happens, OK? You can leave the Sparkfun board attached, it will not be involved.

    http://learn.parallax.com/propeller-c-simple-protocols/diy-i2c

  • Hal Albach,
    I test it and it is work.The screen show "testSr =abcdefg".
  • Good, we know that the I2C library is working. As you can see from the code, it is very much the same that you are trying to use with the Sparkfun board, just different pins on the propeller and different device and memory addresses. There is something about the Sparkfun Board that is not quite working with the Activity board. I think we ruled out bus pull up. Have any of the jumpers on the board been changed, particularly the A0 and A1 jumpers on the back of the board. For a 3E address they both should be in the '0' position.
  • Hal Albach,
    A0 and A1 jumpers are in the '0' position back of the board.I don't change it and also use the 3E address for Arduino is work.
Sign In or Register to comment.