chipKIT® Development Platform

Inspired by Arduino™

Basis IO Tempsensor + EEPROM problem

Created Mon, 30 Dec 2013 04:10:33 +0000 by tcsaba101


tcsaba101

Mon, 30 Dec 2013 04:10:33 +0000

Hi, I am new on this forum. I can't get work the Tempsensor and the EEPROM on the Basic IO board together. Both working well independently. I also have other I2C devices working well alone (PmodRTCC, INA219) but doesn't work if combining with other i2c devices! What is the solution?

I need to use the INA, the RTCC, and the EEPROM together on the i2c bus.

Thanks


majenko

Mon, 30 Dec 2013 10:31:07 +0000

Yes, I can see the problem - my eyesight is so good I can read your code from the other side of the world.

For the benefit of those without such good eyesight, how about posting your code here so we maybe have a chance of working out what is wrong...?


tcsaba101

Mon, 30 Dec 2013 14:10:29 +0000

To sharpen your eyesight I will put together the sketch and the varations I tried with the result.

It is very simple I have combined the basic IO Tempsensor and EEPROM examples bundled with the packade (downloaded from Digilent).

I come back later with the code this evening. I want to be specific, so need some time.

Thanks, Csaba


tcsaba101

Mon, 30 Dec 2013 21:40:04 +0000

This is a working version, but only the EEPROM in function, the Tempsensor codes are killed.

#include <IOShieldTemp.h> #include <IOShieldEEPROM.h> #include <Wire.h>

char buf[26]; char single; int i;

void setup() { Serial.begin(57600);

delay(100); //IOShieldTemp.config(IOSHIELDTEMP_ONESHOT | IOSHIELDTEMP_RES11 | IOSHIELDTEMP_ALERTHIGH); //IOShieldTemp.setTempLimit(IOShieldTemp.convFtoC(78)); // 78.0F ~ 25.5C //IOShieldTemp.setTempHyst(24); // 75.2F ~ 24.0C delay(100); }

void loop() { float tempF, tempC;

/*TempSensor part */ // tempC = IOShieldTemp.getTemp(); // tempF = IOShieldTemp.convCtoF(tempC);

Serial.print(tempC); Serial.print(" C, "); Serial.print(tempF); Serial.print(" F"); Serial.println(); Serial.println();

delay(100); /* EEPROM part*/ IOShieldEEPROM.writeString(0,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");

IOShieldEEPROM.readString(0, buf, 26);

Serial.print(buf); Serial.println();

IOShieldEEPROM.write(20,'#'); IOShieldEEPROM.write(23,'€');

IOShieldEEPROM.readString(0, buf, 26); Serial.print(buf); Serial.println();

single = IOShieldEEPROM.read(25); Serial.print(single); Serial.println(); Serial.println();

delay(1000);
}

Right now I don1t see how to copy a sketch on the best way. I am experimenting using the forum. [attachment=0]Képkivágás.JPG[/attachment]


tcsaba101

Mon, 30 Dec 2013 21:46:00 +0000

If I enable the configuration command of the Tempsensor, then stops the communication, noting written to the Serial monitor.

The code: #include <IOShieldTemp.h> #include <IOShieldEEPROM.h> #include <Wire.h>

char buf[26]; char single; int i;

void setup() { Serial.begin(57600);

delay(100); IOShieldTemp.config(IOSHIELDTEMP_ONESHOT | IOSHIELDTEMP_RES11 | IOSHIELDTEMP_ALERTHIGH); //IOShieldTemp.setTempLimit(IOShieldTemp.convFtoC(78)); // 78.0F ~ 25.5C //IOShieldTemp.setTempHyst(24); // 75.2F ~ 24.0C delay(100); }

void loop() { float tempF, tempC;

/*TempSensor part */ // tempC = IOShieldTemp.getTemp(); // tempF = IOShieldTemp.convCtoF(tempC);

Serial.print(tempC); Serial.print(" C, "); Serial.print(tempF); Serial.print(" F"); Serial.println(); Serial.println();

delay(100); /* EEPROM part*/ IOShieldEEPROM.writeString(0,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");

IOShieldEEPROM.readString(0, buf, 26);

Serial.print(buf); Serial.println();

IOShieldEEPROM.write(20,'#'); IOShieldEEPROM.write(23,'€');

IOShieldEEPROM.readString(0, buf, 26); Serial.print(buf); Serial.println();

single = IOShieldEEPROM.read(25); Serial.print(single); Serial.println(); Serial.println();

delay(1000);
}


tcsaba101

Mon, 30 Dec 2013 21:53:13 +0000

When I put in memo the EEPROM commands, and enable the Tempsens, working well.

The code:

#include <IOShieldTemp.h> #include <IOShieldEEPROM.h> #include <Wire.h>

char buf[26]; char single; int i;

void setup() { Serial.begin(57600);

delay(100); IOShieldTemp.config(IOSHIELDTEMP_ONESHOT | IOSHIELDTEMP_RES11 | IOSHIELDTEMP_ALERTHIGH); IOShieldTemp.setTempLimit(IOShieldTemp.convFtoC(78)); // 78.0F ~ 25.5C IOShieldTemp.setTempHyst(24); // 75.2F ~ 24.0C delay(100); }

void loop() { float tempF, tempC;

/*TempSensor part */ tempC = IOShieldTemp.getTemp(); tempF = IOShieldTemp.convCtoF(tempC);

Serial.print(tempC); Serial.print(" C, "); Serial.print(tempF); Serial.print(" F"); Serial.println(); Serial.println();

delay(100); /* EEPROM part*/ //IOShieldEEPROM.writeString(0,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");

//IOShieldEEPROM.readString(0, buf, 26);

Serial.print(buf); Serial.println();

//IOShieldEEPROM.write(20,'#'); //IOShieldEEPROM.write(23,'€');

//IOShieldEEPROM.readString(0, buf, 26); Serial.print(buf); Serial.println();

//single = IOShieldEEPROM.read(25); Serial.print(single); Serial.println(); Serial.println();

delay(1000);
}

[attachment=0]Képkivágás2.JPG[/attachment]


tcsaba101

Mon, 30 Dec 2013 22:06:19 +0000

And now if I am putting in effect the first write command in the sketch to the EEPROM (IOShieldEEPROM.writeString(0,"ABCDEFGHIJKLMNOPQRSTUVWXYZ");), the communication stops.

I know there are a lot of ways to get forward checking what is happening, but possible it is some simple fault.

What is wrong?

I tried also on MPIDE, there I had to put even the #include "" command in memo to get working the remaining code.

I hope I can use the libraries, I shold not go to Wire or lower level.....


majenko

Mon, 30 Dec 2013 22:30:05 +0000

Both the IOShield libraries call the Wire.begin() method in their constructors. Personally I don't like calling things like that in a constructor, it's not really a good idea as you cannot guarantee the order things happen in.

Also, I am sure I have seen it before where two Wire.begin() calls make the system lock up (it's trying to initialize stuff that's already initialized).

Try commenting out the Wire.begin() method from one of the libraries (not both) and see if that helps. If not, try the other one instead - the order they happen in may be important.

Oh, and it's good to see I have a convert to the wonderful world of UECIDE ;)


tcsaba101

Tue, 31 Dec 2013 09:03:09 +0000

First of all many THANKs for creating UECIDE world! :D UECIDE is my top favorite compared to Mpide. My points: There are visible line numbers!!! I can read the console, because the font can be changed!! I can change the Serial Monitor fonts to be readable! Serial Monitor is only disabled when uploading, doesn't quit! I think it is loading faster, at least I feel this....

I think I know very little about UECIDE features, but really that made my life easier. I could improve with an UECIDE detailed help, tutorial, please give me links.

Regarding the topic:

You must be right with locking, it stucks up somwhere. I have built in the "wrong" code an "intelligent debugger utility" :o using another demo, "blinking without delay" and it is not blinking when the wron code loaded, does nothing. Then watcing the LEDs what they are doing, I have invented: LD4,LD5 LEDs on the uno32 board is showing the bootloader activity. When you upload the code LD5 on,LD4 is blinking fast. After uploaded, LD5 off, LD4 blinking slower, the bootloader still in operation, because my code still not running. Then in normal operation they go off, and start the code has been loaded.

But in this case after loading the faulty code fast LD4: fast blinking, slow blinking, then remains on, showing us there is a problem, and the code does not start. I haven't founded clear reference about it, but those LEDs are definitely shows some bootloader status.

I don't fully understand what the "constructor" means, but i think you meant:

  • the wire.begin(); is an initializing function of the i2c bus, . it should be called only once, then it should be closed (if possibe), then you can call again, etc,
  • it is built in every library (or constructor) what is included in the code,
  • then it makes multiple call it can make problem (this is the example). So it looks like I have to build/rebuild my own library of devices or use only the "wire.functions()".

So according to your recommendation I commented out the wire.begin(); from the EEPROM lib. And it works! Thanks for the idea!

Can you help me with straightforward reference links to understand library construction, how is the constructor idea, etc?

I am out of electronic development life for 20 years (I am electronic engineer but have changed for business life "engineering") and now I am building a car battery rejuvenator & logger for my pleasure with chipKIT uno32/uc32. (I just realised I have to use the WF32 board, that gives the most features onboard what I need).

I have recognised you are one of the most active contributor of this forum! Probably you have in your mind some ideas for my missing ideas: I am still searching for the best options (parts, devices, ideas, etc.) for the following functions of the system:

  • pH sensor what I can hang in the battery opening and reguraly measuring the pH value of the sulfuric acid.
  • programmable load (minimum 10 bit resolution) max.10A (12V) to disharge the batteries,
  • programmable current source (min. 8bit resolution) till 5A/18V to qualify and overcharge the battery, I am just playing the idea to develop a programmable current source what can be used as a programmable load from the power supply direction, and current generator on the output. (when a day will be 24 hours plus sleeping...)

Surfing on the net I see there are almost infinite possibilities, but on one hand the financial budget is limited, and the other hand the time budget also limited to deal with. It is much enough time consuming to build the code with my idea and debug it. I am very happy about this forum to save me time and energy.

But the optimal hardware is essential. Hope you or other contributors can make some light for me in the today's electronic jungle for the optimum solution.

Thanks, Csaba


majenko

Tue, 31 Dec 2013 11:03:51 +0000

The constructor is the code that is called when you create an object from a class. For instance, the EEPROM library contains the line:

IOShieldEEPROMClass IOShieldEEPROM = IOShieldEEPROMClass();

That creates a new object (IOSheildEEPROM) from the class (IOShieldEEPROMClass) with no parameters. When that happens the constructor is called

IOShieldEEPROMClass::IOShieldEEPROMClass()
{
    #if defined(_BOARD_MEGA_)
        PORTSetPinsDigitalIn(IOPORT_B, BIT_4 | BIT_5);
    #endif
    Wire.begin();
}

You have no control over when that is called, all you can do is guess that it is called at some point during system startup, and probably in order within CU (Compilation Unit - single CPP file), but further than that, who knows when it happens?

You really shouldn't reference other libraries in a constructor as you can't guarantee that the library you are referencing (Wire in this case) has been initialized properly yet; i.e., has the constructor been run before this constructor? With the Wire library it's not actually a problem as the constructor is empty, but you see the problem. There should really be an IOShieldEEPROM.begin() method that calls the Wire.begin() so you can be sure that the Wire constructor has been called.

The lock-problem you are seeing should really be fixed in the Wire library, not the individual device libraries. It should really be changed so that it can only be begun once and further begins have no effect. It's simple enough to do - maintain a flag which is set the first time it is begun, and subsequent begins examine that flag to abort the begin - an end() call resets the flag. Better would be to maintain a counter of begins, so it is only closed off if the counter (incremented by begin and decremented by end) reaches 0. Maybe I'll quickly implement it so it'll be in a future release... (click click click ... pull request done). I'm just building a new UECIDE chipKIT core too with it in...

Now... ideas for you project (it certainly sounds an interesting one)... I'd say you probably have the electronics side of things nailed, so what ideas could I add? Let me think:

Make a high-current digital variable resistor out of MOSFET(s) and a DAC - maybe the MCP4822 (dual 12-bit precision DAC with internal voltage reference - 0-4.095V in 1mV steps, or 0-2.0475V in 0.5mV steps) - that could be a variable dummy load, or with a current sense shunt and ADC connection for feedback, a constant current sink.

For desulphating I guess you want maybe a (IIRC) 1KHz AC power signal? Unfortunately the OC module in the PIC32 is a little basic compared to some other chips (like the dsPIC33 'MU810) and can't directly output positive and negative pulses, only positive. My initial thoughts were that a 1KHz PWM signal at 50% duty cycle fed into a specially constructed (with built-in signal inversion) H-bridge might work, but on reflection that doesn't take into account MOSFET (if you use MOSFET) crowbaring as there'll be no dead time between the two phases. So you may be better off doing it manually manipulating IO pins and maybe a timer interrupt - BOTH off, A on, BOTH off, B on, BOTH off... [attachment=0]400px-Block_PWMMotor_Illustration_DeadTime.png[/attachment]


tcsaba101

Tue, 31 Dec 2013 14:09:32 +0000

I will study in details your answer. I have to catch up to this level of C++. In the code I will try first to comment out in the second and subsequent libs the wire.begin(); command.

Does exsist some reference about library structure and operation principle?

Thanks for hw ideas. I like your idea of power variable resistor. Do you have a in mind a solution of end stage? The control and sensing part I have solution. I would use as much ready parts, modules as possible to find on the market. I was thinking on a DC D-class amplifier endstage with varable gain. It should be a switching supply because of the dissipation in the current source mode. In load mode it is regardless, everething can be dissipated on a resistive part.

For desulphating I am testing the followings:

  • pulsing
  • overcharging to 16V or above.

I am also thinking to try AC desulphating later on. This seems to be very useful on fully dead batteries.

Now I am experimenting on new batteries stayed 1-2 years on stock what has nice desulphation without other issues.

Thanks, Csaba

Ps. How you put in the Post the Code fragments in brakets?


majenko

Tue, 31 Dec 2013 14:42:56 +0000

I will study in details your answer. I have to catch up to this level of C++. In the code I will try first to comment out in the second and subsequent libs the wire.begin(); command. Does exsist some reference about library structure and operation principle?

Not really. A library is pretty much an abstract human concept. It's just a header file and (usually) a .cpp file (and sometimes more support files). They usually contain one or more class. You can read more about classes here: [url]http://www.cplusplus.com/doc/tutorial/classes/[/url]

Thanks for hw ideas. I like your idea of power variable resistor. Do you have a in mind a solution of end stage? The control and sensing part I have solution. I would use as much ready parts, modules as possible to find on the market. I was thinking on a DC D-class amplifier endstage with varable gain. It should be a switching supply because of the dissipation in the current source mode. In load mode it is regardless, everething can be dissipated on a resistive part.

A class D amplifier is nothing more than PWM switching a higher voltage and/or current. If you're generating a PWM signal as a source then that can be used to amplify it, yes. You'd want a single-ended one though really, not a differential one, as you want to keep your ground reference. After that you'd need to filter it to create a stable voltage, so some big chokes and capacitors would be wanted (a couple of stages of cheby?). For current feedback you would really want a high-side shunt, so as to not offset the ground at all, and for that a proper high-side current sense amplifier could be useful, say the AD8215.

For desulphating I am testing the followings:

  • pulsing
  • overcharging to 16V or above. I am also thinking to try AC desulphating later on. This seems to be very useful on fully dead batteries. Now I am experimenting on new batteries stayed 1-2 years on stock what has nice desulphation without other issues. Thanks, Csaba Ps. How you put in the Post the Code fragments in brakets?

You use the [code]...[/code] tags. It also escapes things that often cause problems, like

for( ; ;) {
}

becoming: for( ; ;) { } and

myArray*[j];

becoming myArray[i][j];*


bperrybap

Tue, 31 Dec 2013 22:34:06 +0000

Ironically, I just ran into the issue of multiple Wire.begin() on calls using an UNO32 yesterday. (I haven't seen this issue on the AVR Wire library.)

I tracked it down to the twi_init() function down in the pic32 libraries/Wire/utility/twi.c Here is the line that creates the issue:

/* Enable the interrupt controller and turn on clock stretching.
	*/
	ptwi-&gt;ixCon.reg = (1 &lt;&lt; _I2CCON_ON) | (1 &lt;&lt; _I2CCON_STREN);

But it is more complex than just that line.

The system really doesn't lock up there, as the twi_init() function does return. It gets stuck on future Wire calls.

I'm not yet familiar with the pic32 i2c hardware but perhaps that initialization is creating some sort of glitch on the i2c bus that confuses the slave? Anway, the quick & dirty answer is to simply put a static flag at the top of the twi_init() function that returns after the first call.

i.e. something as retarded as:

static int initalzed = 0;

    if(initalized++)
        return;

Just above:

setIntVector(_TWI_VECTOR, I2CHandler);

--- bill


majenko

Wed, 01 Jan 2014 00:25:50 +0000

I have already crafted something similar, but done it at the class level, not the underlying driver level. That way it can interact properly with the begin/end concept of libraries (though there wasn't an end() function before). The changes are pending in a pull request for MPIDE, and are live in the latest chipKIT core for UECIDE.


tcsaba101

Wed, 01 Jan 2014 07:40:09 +0000

If I control, that only one Wire.begin(); has been called, the i2c working with INA219, EEPROM, RTCC, Tempsensor hooked on. So if you know what you are doing it works.

If there is a fool free general solution please send me the code.


majenko

Wed, 01 Jan 2014 10:50:35 +0000

If there is a fool free general solution please send me the code.

In UECIDE go to "tools -> plugin manager" and find the chipKIT core (cores->pic32->chipKIT). Select it, then press the "upgrade" button. After a couple of moments it should be all fixed.


bperrybap

Wed, 01 Jan 2014 19:20:56 +0000

I have already crafted something similar, but done it at the class level, not the underlying driver level. That way it can interact properly with the begin/end concept of libraries (though there wasn't an end() function before). The changes are pending in a pull request for MPIDE, and are live in the latest chipKIT core for UECIDE.

I guess it could be argued either way. My feeling is that the problem is actually in the low level h/w intialization code vs the class code, so it should be fixed there. But if it the fix is going to be put into the class code, then I would prefer a big fat warning put into the code specifying that the twi_init() funciton is not properly handling the hardware and therefore can only be called once.

Further implementation discussion here: [url]https://github.com/chipKIT32/chipKIT32-MAX/pull/396[/url]

--- bill