Pulse a 5V VCC pin with 18V to set EEPROM values... say what!?

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. :slight_smile:

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. :slight_smile:

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? :confused:
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

Tjaart:
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..

Hi Wawa

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

:o

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..

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.

:slight_smile:

Second option.

Leo..

You should not cross-post: Allegro A1335. Is it any good? Will soon find out. - Sensors - Arduino Forum.

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 !

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.

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: Arduino Controlling transistor - #2 by dlloyd - Project Guidance - Arduino Forum. Add two diodes to VCC for 19V and 5V and you can write a sketch to create those pulses.

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 :frowning:
The angle adress on chip is

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.

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

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:

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:

#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?

Tjaart:
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..

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 ?

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

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.

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 :slight_smile:

:slight_smile: 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.

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.

#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.

You want to use that special feature that the IRP keeps the register address at 0x20 when reading the angle. I wanted to go slow and keep that for later.

The "uint16_t" is a unsigned int of 16 bits.
The normal 'int' type is 16 bit in a Arduino Uno and 32 bit in a Arduino Due. That is why the "uint16_t" is used, because that is always 16 bits.

I'm confused with "A1335" and "ANG", the names are so short !
What about "A1335addres" and "ANGregister" ?

Both me and the compiler are confused with this:angle_deg = raw_data*360/4096;
The "raw_data" is a unsigned integer, the 360 and 4096 are integers, and after the calculation it is converted to a float. I prefer to do that calculation with floating point calculations.

Don't use a Wire.endTransmission() after a Wire.requestFrom(). That is a number 2 :wink:

Divide by 16 for binary to decimal ? When a variable has a certain value, that value can be printed as a decimal number or a binary number, but the value of that variable is the same. If you put 180 in a variable, that variable is 180. A number is a number.

I prefer to use local variables when it is used locally. You can declare local variables in the loop(). If you remove the global 'angle_deg' and 'raw_data', then you can try this:

void loop() {
  unsigned int raw_data;          // The raw data from the sensor ANG register.
  float angle_deg;                     // After math on value store a degree out of 360

  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
  raw_data |= Wire.read();                // OR function to store low byte
  
  raw_data &= 0x0FFF;          // strip highest 4 bits with bitwise AND operation
  
  angle_deg = (float) raw_data / 4096.0 * 360.0;   // calculation with float

  Serial.print("Angle degree > ");          // Print angle in degrees
  Serial.println(angle_deg);
  Serial.println (" ");

  delay(1500);  // wait so human can read it
}

The "(float) raw_data" means that "raw_data" is converted into a float value, and after that the math is done with 4096.0 and 360.0
Do you see the "4096.0" and "360.0" instead of the "4096" and "360" ?
When the compiler sees "4096.0" it uses that as a float number. When the compiler sees "4096" it uses that as integer number.

Please show your new sketch. I prefer to see the new sketch, even if only a comma has changed.

Hi Koepel

After your help I got it working. Vid

The oscilloscope I ordered never arrived from China but did get my money back.
So Have to order that again from some where else.

But I went on with the project and got some cheap steppers, Arduino due and switch mode power supply and so on.

Working towards Due running four steppers with the sensors as position fed back for steering and 4X DC motors.

Parts still arriving. This is what I have so far:

picture to big! any way... It just showed the Due with parts assembled in newly 3D printed test setups.

Should have more parts and time next week to do better post.

Nice. I think you need to take a few samples with analogRead() and use the average. That will make the value a lot more steady.

An oscilloscope ? There are very nice USB oscilloscopes. Then you don't have to pay for a screen. A digital oscilloscope is not the same as an old analog oscillope from a yard sale, you need a high sample rate or you miss a lot.
It did not arrive ? I have changed from Ebay to AliExpress. With Ebay it is very hard to get money back. I think that the sellers on AliExpress get their money after I confirm that it was received, so the sellers try a little harder to do their best.
The saleae USB oscilloscopes are very nice, but also super extremely over-the-top totally nuts expensive. However, in my opinion they set the standard for hardware and software for a good product.
There are cheaper USB oscilloscopes that can be used with a open source interface: PulseView/sigrok.
A poor man's solution is a attenuator of 1:10 with resistors and use the line-in of a computer together with Audacity. That is even dual channel (stereo).

This little fella Allegro A1335 is used in cars for controlling their ABS and ATC Tracking system so i think this is a realy good sensor. I am as you suprised there are so little information about this angle sensor and little use by Arduino friends?

I dont understand that because there should be many places wher a high precission angle sensor is needed. And specially when it dont have any mechanically contact with the sensor it can get dirty and greasy without any problem, and they use them in cars.

I am looking as you Tjart for a Wind director sensor and i just ordered a couple. Did you got your to finally work?

There is more codes for the presessor A1332 you can look at, i think its the same code.

Onwards
Ole Sweden