Go Down

Topic: Pulse a 5V VCC pin with 18V to set EEPROM values... say what!? (Read 465 times) previous topic - next topic

Tjaart

I went a ahead and bought 10xA1335 sensor chips and I am planning to use them with I2C communication.
Now they come pre-programmed with a I2C address and two hardware pins to change the address so you can use 4 of them out of the box by setting the hardware pins. :)

When you want to use more than 4 one need to change the first 5 bits in the register to a new address, coupled with the hardware pins.. gives you another 4 sensors and so on. :)

To set the new address in EEPROM memory you set a couple of enable bits and register addresses. Once everything is set you need to pulse the VCC pin (normally at 5V) with something like 18V to make it permanent.

How do you that? :smiley-confuse:
Extracts from Data sheet and programming manuals:

Address: 0x319 (continued)
EEPROM Register Reference (continued)
I2C_SLAVE_ADR [6:2]
I2C Slave Address
Sets the 5 MSB of the I2C slave address. 2 LSB of address set by the
logic state of the SA0 and SA1 pins.

The final step in writing to EEPROM is sending programming pulses on the EEPROM programming pin (the VCC pin) to set  the bitfields. The VCC pulse profile necessary for EEPROM programming is shown in Figure 17. Minimum and maximum times
are described in Table 17. After EEPROM has been written, it is recommended to cycle power to the device.

Pulse Voltage min: 18V Typical: 19V Max:19.5V

Wawa

When you want to use more than 4 one need to change the first 5 bits in the register to a new address...
You don't have to.
Just use one address pin as 'chip select' for two devices.
Then you can select as many 'two_address_pairs' as you want.
Leo..

Tjaart

Hi Wawa

I had another read in the programing manual for A1335 and I do not follow/understand your solution.

 :o

Wawa

Nothing to do with the device. Just general I2C stuff.

An I2C master can only address (talk to) one device at the time.

If you manipulate the address pins of a device (with a digital output pin), then you can change the address on the fly.

Set four pairs (eight devices) to two address that you don't read.
And set one pair to addresses that you do read.
Leo..

Tjaart

Oooo, thats a need trick.
Will keep it in mind but would still like to know how to program the A1335 properly.
Seems there is a way to program EEPROM by pulsing the VCC pin.

 :)

Wawa

Second option.

https://learn.adafruit.com/adafruit-tca9548a-1-to-8-i2c-multiplexer-breakout/overview

Leo..

Koepel

You should not cross-post: https://forum.arduino.cc/index.php?topic=538448.0.

Can you give a link to the manufacturers page where to find the datasheet and the programming manual ?

A laptop power supply is often 19V. You could have two diodes to VCC. One diode for the 5V and one diode for the 19V. The 19V can be applied by for example two transistors or maybe even by touching a wire with 19V to the diode.

It is a 5V chip. That means that when VCC gets 19V, the other pins still are at 5V... I hope.
If something goes wrong, you can damage the chip, the Arduino board and your computer.

Small companies might build a dedicated device that changes the I2C address.
Large companies might ask the manufacturer do this for them.

Why all this trouble ? Use SPI !

Tjaart

Thanks Koepel
The first thread was about getting advice/reviews for the sensor but now I am stuck on this issue.
Did not think to add links between the posts.

I2C would be better because it uses less pins. If I fail at that then I will have to go with SPI.

Data sheet
Programming manual

I am having issues with my internet provider. Sorry for the long delay in replying. I am not a time waister, this looks like a good sensor to add to Arduino library.

Datasheet: page 12 programming modes, 13 writing to EEPROM, 17 circuit diagram, 22 Linearization
Programming manual: (17-20) I2C programming, 58 programming EEPROM and pulse description, (76) I2C register description.

again thanks for the help.

Koepel

That is very specific. Two pulses to VCC between 18 and 19.5 V and a duration between 8 and 11 ms.

Because you can damage many things with 19V, I suggest not to try it.

A high side switch with two transistors is something like this: http://forum.arduino.cc/index.php?topic=323048.msg2232565#msg2232565. Add two diodes to VCC for 19V and 5V and you can write a sketch to create those pulses.

Tjaart

Hi Koepel

Thank you for the advice. I am very interested in a sketch to create the pulses and I googled the high side switch, clamping diodes, optocouplers and so on.

I am just waiting on my oscilloscope I ordered from China to arrive before I give this a go./Attempt changing the I2C address.

In the meanwhile I soldered my first 14-pin TSSOP component, 3D printed a test setup and connected 1X A1335 to test the I2C communication. I would like to know how fast it responds to a change in magnet position.

Here is a video instead of pick: A1335 test setup
How does one post a pick from your computer, not a URL?

New issue :(
The angle adress on chip is
Quote
Address: 0x20:0x21 (ANG)
Just starting out with I2C and I did google and read forum but no one covered this:

So start wire library and call device address, next point to register,? But my register has 2X addresses namely 0X20 and 0X21.
The example code always point to one register 'name' and requests two bytes of data.

 :smiley-sad-blue: My internet keeps dropping out and then I have to start post over.. so I posting this now before it drops out again.

Tjaart

Unknown but this will be my third attemt at continue post... my internet drops out.

Still stuck on addressing the ANG register from programming manual (Page 9). Decide to mix match code between three other projects found on net. All have some components similar to my setup.

Since i cant use the ANG register I am going with accessing the High byte and then Low byte in my code.

Rite now I am stuck on line 17 with this error message:
Quote
raw_data = Wire.read(ANG_regL);// store data

                            

exit status 1
no matching function for call to 'TwoWire::read(int)'

And my code thus far:
Code: [Select]
#include <Wire.h>
int A1335 = 0x0F;                             // I2C address of sensor
#define ANG_regH 0x20                        // High byte for ANG register
#define ANG_regL 0x21                          // Low byte for ANG register
int raw_data;                                     // Some where to store data and shift bits to get angle value only
float angle_deg;                                      //After math on value store a degree out of 360

void setup() {
  Serial.begin(9600);                            // use monitor
  Wire.begin();                                        //initiate wire library
  Wire.write(A1335);                                // I2C adress for sensor
  // Wire.write(ANG);                // Do not know how to declare/setup this register so
                                                            //attempting to access bytes
  Wire.write(ANG_regH);                           // point to High byte for ANG register
  Wire.write(ANG_regL);                          //point to Low byte for ANG register
  Wire.endTransmission();
  // stop setup, both data bits in ANG register on sensor A1335 pointed to

}

void loop() {
  
  Wire.requestFrom(A1335,ANG_regH);               // read value from High bit
  raw_data = Wire.read(ANG_regH);                   // store data
  raw_data = raw_data <<8;                             // shift data over to make space for Low byte
  Wire.requestFrom(A1335,ANG_regL);              // read Low byte
  raw_data |= Wire.read(ANG_regL);                // OR function to store low byte
  raw_data = raw_data <<4;                           // shift 4 bits left to drop 'settings' bits
  raw_data = raw_data>>4;                            // shift back to get only angle value in stored memory
  Serial.print("Raw data - ");                           // Display the data in serial monitor
  Serial.print(raw_data);
  delay(3000);                                                //wait a bit so a human can read it
  angle_deg = ((raw-data)(360/4096));            // turn value to degrees, formula from data sheet
  Serial.print("Angle degree - ");                     // Print angle in degrees
  Serial.print(Angle_deg)
  delay(3000);                                               // wait so human can read it

}


Should I continue asking these Questions her or should I ask them in the I2C/comunication section or the code Q? section?

Wawa

Unknown but this will be my third attemt at continue post... my internet drops out.
The unfinished or not sent post will be in your drafts folder.
Click on your avatar, and click on "Show Drafts".
From there you can copy/paste/resend.
Leo..

Koepel

With the "reply" button (not the quick reply) it is possible to attach a picture. Perhaps that comes available when you have enough posts. Sometimes I use tinypic.com, and then you can add the picture url between [ img ] and [ / img ]. There is also a button for those tags.

I took a closer look at the Datasheet and the Programming Manual. That is not a easy chip. You are trying for the first time to write I2C code with such a chip, that is hard.

Can you avoid to use "address" ? Be more specific to avoid confusion.
"I2C address" = the address of the chip on the I2C bus
"register address" = the value of the register inside the chip that points to a certain register.

In the Progamming Manual the "register address" is called "Interface Register Pointer" (IRP).

When you want to try to read the ANG register, the "register address" has to be set to 0x20, and then two bytes can be read. The two bytes can be combined for a 16 bit value. The "register address" itself is a single byte.

There is a trick for the ANG register. Once the "register address" of 0x20 is set, there is no need to set it again. The ANG data can be read many times after that. I suggest to keep that for later.

Are you sure that 0x0F is the I2C address ? Can you add a test for that ?
Code: [Select]

int A1335address = 0x0F;                             // I2C address of sensor ?

void setup()
{
  Serial.begin( 9600);
  Serial.println( "Sketch has started");
  Wire.begin();

  Wire.beginTransmission( A1335address);
  byte error = Wire.endTransmission();
  if( error == 0)
  {
    Serial.println( "Sensor A1335 found");
  }
  else
  {
    Serial.println( "Error, sensor not found");
  }
}


You could write a funtion to read 16 bits from the A1335. To be sure that a 16 bits unsigned variable is used, there is a type for that: uint16_t
Code: [Select]

uint16_t readU16( int registerAddress)
{
  uint16_t data;

  Wire.beginTransmission( A1335address);
  Wire.write( registerAddress);
  Wire.endTransmission( false);    // parameter 'false' for a repeated start

  Wire.requestFrom( A1335address, 2);   // request two bytes
  data = Wire.read();       // first byte is MSB
  data <<= 8;          // shift the MSB into its location
  data |= Wire.read();    // second byte is LSB

  return( data);
}


Note: It seems that the chip has a special mode that uses a extended I2C address. I think that the Arduino Wire library does not support that.

Tjaart

That is really useful information. Thank you. I will adapt my code accordingly thou it might take me rest of the day.

Great to know about the draft function.
The I2C bus address I am using was found through the I2C scanner sketch.
It is different to what I thought I set it to in hardware, so I will recheck that as well.

Great stuff  :)

Tjaart

 :) Update

Attempted your code but could only get " 0 " as output from sensor. Since I am not at you coding level, de-bugging it would take to long. These "unit16_t" thingies have me scratching my head.

Code: [Select]
int A1335address = 0x0F;                             // I2C address of sensor ?
int registerAddress = 0x20;
#include <Wire.h>
unsigned int data;

void setup()
{
  Serial.begin( 9600);
  Serial.println( "Sketch has started");
  Wire.begin();

  Wire.beginTransmission( A1335address );
  byte error = Wire.endTransmission();
  if( error == 0)
  {
    Serial.println( "Sensor A1335 found");
  }
  else
  {
    Serial.println( "Error, sensor not found");
  }
}

 uint16_t readU16( int registerAddress)
{
  uint16_t data;

  Wire.beginTransmission( A1335address);
  Wire.write( registerAddress);
  Wire.endTransmission( false);    // parameter 'false' for a repeated start

  Wire.requestFrom( A1335address, 2);   // request two bytes
  data = Wire.read();       // first byte is MSB
  data <<= 8;          // shift the MSB into its location
  data |= Wire.read();    // second byte is LSB
  data <<= 4;         // first 4 bits from MSB not required
  data >>= 4;         // only angle measurement bits left

  return( data);
}
void loop() {
  uint16_t readU16( int registerAddress);
  Serial.print(data,BIN);
  delay(300);

}


So I used your advise in my own code (witch were not to far of from what I was attempting) and I got it working..... sort of. I still need to calculate the angle in degrees. For some reason mine don't.

But that is all I have time for rite now. Will get back to this later while I am waiting on me oscilloscope.

Code: [Select]
#include <Wire.h>
int A1335 = 0x0F;                                // I2C address of sensor
#define ANG 0x20                                //IRP (starting address for ANG register)
unsigned int raw_data;          // Some where to store data and shift bits to get angle value only
float angle_deg;                                    //After math on value store a degree out of 360

void setup() {
  Serial.begin(9600);// use monitor
  Serial.println( "Sketch has started");   // Code from Koepel post in Arduino post
  Wire.begin(); //initiate wire library
  
    Wire.beginTransmission( A1335);      //Koepel post to test I2C bus address of sensor
  byte error = Wire.endTransmission();
  if( error == 0)
  {
    Serial.println( "Sensor A1335 found");
  }
  else
  {
    Serial.println( "Error, sensor not found");
  }                                       // End of Koepel code, Thanks for your help.
  
  Wire.beginTransmission(A1335);         // I2C bus adress for sensor
  Wire.write(ANG);                      // Interface Register Pointer (IRP).
  Wire.endTransmission();               // ANG register on sensor A1335 pointed to

}

void loop() {
  
  Wire.requestFrom(A1335,2);            // request two bytes from sensor
  
  raw_data = Wire.read();                // read first/High byte
  raw_data <<= 8;                       // shift data over to make space for Low byte
  Serial.print ("first byte >");         // Print High byte in monitor
  Serial.println (raw_data,BIN);
  
  raw_data |= Wire.read();                // OR function to store low byte
  Serial.print ("both bytes > ");         //Print both bytes in monitor
  Serial.println (raw_data,BIN);
  
  Wire.endTransmission();
  
  raw_data = raw_data <<4;                 // shift 4 bits left to drop 'settings' bits
  raw_data = raw_data>>4;                  // shift back to get only angle value in stored memory
  
  Serial.print("Raw data shifted - ");     // Desplay the angle value in serial monitor
  Serial.println(raw_data,BIN);
  
  angle_deg =(float) raw_data / 16;         // 16 bit binary to decimal
  Serial.print ("converted > ");            // Print dec value
  Serial.println (raw_data);
  
  angle_deg = raw_data*360/4096;           // turn value to degrees, formula from data sheet
  Serial.print("Angle degree > ");          // Print angle in degrees
  Serial.println(angle_deg);
  Serial.println (" ");
  delay(3000);// wait so human can read it

}


Here's a short VIDEO of where I am at.

Go Up