Created Thu, 29 Aug 2013 01:44:51 +0000 by unexpectedly
Thu, 29 Aug 2013 01:44:51 +0000
Hey all. Resident newbie here. I'm porting my current project from Arduino to chipKIT and it has been about 5 times more difficult than I was expecting. The only code so far that has ported is blink(). No one already associated with chipKIT is ever allowed to say or imply that working Arduino code will transfer over here without a fight...
I think I got a handle on SPI.
And now I'm working on the extreme most easy gizmo I have ever played with in Arduino, an I2C real time clock. My code worked in Arduino. Worked. On the 1st try. Now I'm 3 or 4 hours into banging my head against chipKIT again...
I'm using NKC Electronics arduino proto shield on my uC32. I like this one because it breaks out I2C from A4 and A5 in a grid in bottom corner. I used that as a chance to put 2.2k pull-up resistors on the C and D lines.
I tried it first with 0x68 and then I read about how uC32 doesn't use I2C addressing and the secret, undocumented, thing to do is /2 or >>1.
Here's the code:
#include <Wire.h>
char date[30];
#define I2C_DS1307_ADDRESS 0x68
byte bcdToDec(byte val){ return ( (val/16*10) + (val%16) ); }
byte decToBcd(byte val){ return ( (val/10*16) + (val%10) ); }
void getDate( char * buffer ){
int address = I2C_DS1307_ADDRESS >> 1;
// From the exmaple SFRRanger_reader.pde ...
// transmit to device #112 (0x70)
// the address specified in the datasheet is 224 (0xE0)
// but i2c adressing uses the high 7 bits so it's 112
Serial.println("Starting transmission...");
Wire.beginTransmission( address ); // Reset the register pointer
Wire.send(0x00);
Wire.endTransmission();
delay(70); // check datasheet for wait time?
int second, minute, hour, weekDay, monthDay, month, year;
Serial.println("sending request");
Wire.requestFrom( address , 7);
delay(70); // check datasheet for wait time?
Serial.println("Getting bytes...");
second = bcdToDec(Wire.receive());
minute = bcdToDec(Wire.receive());
hour = bcdToDec(Wire.receive() & 0b111111); //24 hour time
weekDay = bcdToDec(Wire.receive()); //0-6 -> sunday - Saturday
monthDay = bcdToDec(Wire.receive());
month = bcdToDec(Wire.receive());
year = bcdToDec(Wire.receive());
sprintf( buffer, "20%d-%02d-%02d %02d:%02d", year, month, monthDay, hour, minute );
}
void setup(){
Serial.begin(9600);
// Real Time Clock
Wire.begin();
// setDateTime(); // only used once, in theory... ;)
}
void loop() {
getDate(date);
Serial.println(date);
delay(10000);
}
And the ouput is always:
Starting transmission...
sending request
Getting bytes...
200-00-00 00:00
When the RTC loses its date, it does not return all zeroes. Putting o'scope on and this is the only changes on pins 4 and 5 (confirmed 4 is top and 5 is bottom). It happens with the begin transmission. There is no other activity on the pins.
Pics of the setup... [attachment=2]rtc_scope.jpg[/attachment]
[attachment=1]rtc_i2c.jpg[/attachment]
[attachment=0]i2c_pull_ups.jpg[/attachment]
Any help would be greatly appreciated. I'm beaten down pretty hard by fighting with chipKIT with such "easy" code and want to get back to actual work. Sadly, there is more to get working after this, too. If you look at what this project is, I'm hoping something goes well for me soon... The SPI TFT and the I2C RTC were "slam dunks" in Arduino... :?
Thanks, Chris
Thu, 29 Aug 2013 01:48:16 +0000
Oh, those resistors are 2.7k. Just took the shield out and measured to make sure...
Here's pic of that proto shield: [attachment=0]nkc_electronics_proto_shield.jpg[/attachment]
Thu, 29 Aug 2013 09:41:21 +0000
Hmmm... The last time I did any Wire work was to take an Adafruit library (for the MCP23017) and convert it for the chipKIT and to change it to be an LED display library.
All I had to do was change #include <Arduino.h> to #include <WProgram.h> and add my LED display code. All the wire stuff just worked as is. It already had the code in to switch between Wire.write() and Wire.send() depending on ARDUINO being >= 100.
I don't know what they're on about in those comments. I2C specifies that the first 7 bits of the first byte are the address, and the 8th bit is the read/write bit. To create a whole address bytre from an address ID you left-shift by one bit and OR in the read/write bit. And anyway, the Wire.h library deals with all that side of things for you:
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr); // This sets "READ"
Wire.send(MCP23017_GPIOA);
Wire.endTransmission();
Wire.requestFrom(MCP23017_ADDRESS | i2caddr, 2); // This sets "WRITE"
a = Wire.receive();
ba = Wire.receive();
Thu, 29 Aug 2013 19:54:19 +0000
Hi majenko, thanks for always trying to help me. :)
Yeah, I studied the I2C protocol last night. It would seem I am about the ten thousandth engineer to make a PIC talk to an 1307 RTC. I think I'm going to be stubborn and declare that I will not hand-roll I2C for PIC when it is supposed to be in the Libs and supposed to work.
My code was done in Arduino-land. No need to redo the wheel.
Let us consider your analogy that the Arduino is a saloon car with automatic transmission and chipKIT is rugged 4x4 with multiple gearboxes (and I imagine a PTO on rear axle).
Then why is the chipKIT also like the 1948 Packard Super 8? In that to use I2C, I need to know that by slowing down using the engine, I just drained the carburetor of all its fuel and that to begin running again, I need a gasoline container handy to pour some into the throat of the carburetor whilst someone else is starting the engine and pumping the throttle? Aren't we a little bit past this by 1985? I mean 2005? And yes, the code if I implement I2C manually for this particular cause is from 2005.
A .NET "arduino compatible" came in today. I forgot that I ordered it, actually! I wonder how long it will take for me to get the 1.8TFT and I2C RTC working?
Sooooo, yeah, someone please get back to me when the attached hello world works as it is supposed to (without excuses or hidden procedures required from a reference manual I cannot find). I think I'm going to stubbornly put my foot down and say, "no, sorry, I am above implementing yet another I2C". chipKIT isn't worth my time in this regard. For this I am sorry.
Just did it again on Arduino UNO; I took that proto shield with the RTC soldered up to it and put it on an Uno R3. Worked on the 1st try.
2013-08-29 12:43:42
2013-08-29 12:43:47
2013-08-29 12:43:52
2013-08-29 12:43:57
2013-08-29 12:44:02
2013-08-29 12:44:07
2013-08-29 12:44:12
2013-08-29 12:44:17
2013-08-29 12:44:22
2013-08-29 12:44:27
2013-08-29 12:44:32
2013-08-29 12:44:37
Thu, 29 Aug 2013 20:34:48 +0000
Alas I don't appear to have a DS1307 to hand. Everything else - DS1306 aplenty, DS1302, even an old MC146818, but no DS1307. Strange, I was sure I ordered some samples ages ago to experiment with. Ah well, not to worry - I'll have one here in a few days... good ol' Maxim.
Thu, 29 Aug 2013 20:59:02 +0000
This is the specific gizmo I'm trying to talk to.
Thanks, Chris
PS - to help quantify my frustration, I have sworn off microsoft my whole life... I just install MSVC# and .NET. I feel dirty.
Thu, 29 Aug 2013 21:09:00 +0000
Good man. I knew you were sensible really :)
Sun, 01 Sep 2013 23:05:32 +0000
As written above, that code does not compile with the pre-1.0-ArduinoIDE derived mpide.
[color=#BF80BF]Simply converting the write to send and reads to receive, the above code hangs when trying to receive because the mpide wire.h does a blocking call waiting on the reply. For whatever reason, this hardware never reacts in chipKIT-land, however runs without change in arduino world and also .NET's Netduino.[/color] ... update in reply below.
My first thought was to just grab the post-1.0-Arduino Wire library over, change it to Wire1 and drop it in my Libraries folder. That doesn't work either. There are overloads of print::write() that I'm a tad afraid to go mess with.
In file included from tft_rtc.cpp:55:0:
C:\Users\chris\Documents\mpide\libraries\Wire1/Wire1.h:60:20: error: conflicting return type specified for 'virtual size_t TwoWire::write(uint8_t)'
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:50:15: error: overriding 'virtual void Print::write(uint8_t)'
C:\Users\chris\Documents\mpide\libraries\Wire1/Wire1.h:61:20: error: conflicting return type specified for 'virtual size_t TwoWire::write(const uint8_t*, size_t)'
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:52:15: error: overriding 'virtual void Print::write(const uint8_t*, size_t)'
This fellow's post on Arduino.cc talks about it some...
Sun, 01 Sep 2013 23:18:00 +0000
Whooooooo boy, that made mpide mad.
There's some real classism to sort out!! My programming training from EE-land was light on the classes and overloading, so this isn't really my area.
In file included from C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/HardwareSerial.h:54:0,
from C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/WProgram.h:20,
from C:\Users\chris\Documents\mpide-0023-windows-20130715\.\hardware\pic32\libraries\SPI/SPI.h:53,
from tft_rtc.cpp:7:
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:54:20: error: 'virtual size_t Print::write(uint8_t)' cannot be overloaded
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:50:15: error: with 'virtual void Print::write(uint8_t)'
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:55:12: error: 'size_t Print::write(const char*)' cannot be overloaded
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:51:15: error: with 'virtual void Print::write(const char*)'
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:59:20: error: 'virtual size_t Print::write(const uint8_t*, size_t)' cannot be overloaded
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:52:15: error: with 'virtual void Print::write(const uint8_t*, size_t)'
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h: In member function 'size_t Print::write(const char*)':
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:57:53: error: void value not ignored as it ought to be
In file included from tft_rtc.cpp:55:0:
C:\Users\chris\Documents\mpide\libraries\Wire1/Wire1.h: At global scope:
C:\Users\chris\Documents\mpide\libraries\Wire1/Wire1.h:60:20: error: conflicting return type specified for 'virtual size_t TwoWire::write(uint8_t)'
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:50:15: error: overriding 'virtual void Print::write(uint8_t)'
C:\Users\chris\Documents\mpide\libraries\Wire1/Wire1.h:61:20: error: conflicting return type specified for 'virtual size_t TwoWire::write(const uint8_t*, size_t)'
C:\Users\chris\Documents\mpide-0023-windows-20130715\hardware\pic32\cores\pic32/Print.h:52:15: error: overriding 'virtual void Print::write(const uint8_t*, size_t)'
Sun, 01 Sep 2013 23:27:16 +0000
Ah yes, that's expecting the version 1.0.x print class, not the 0023 version. There are some big changes - not least an extra overloaded write() function that allows writing of an array of bytes.
Sun, 01 Sep 2013 23:43:30 +0000
Simply converting the write to send and reads to receive, the above code hangs when trying to receive because
I didn't run Wire.begin() in Setup() :oops:
I'm pretty sure I didn't make that goof the very first time through as I very :geek: the first several tries.
Sun, 01 Sep 2013 23:48:15 +0000
Hey... don't sweat it. I did the exact same thing today but with SPI. Had something working as a sketch - converted it to a library, kept hanging at the first SPI.transfer(). Couldn't work it out. Finally realized that I'd forgotten the SPI.begin()!!!
Mon, 02 Sep 2013 00:08:40 +0000
So yeah, to confirm, my I2C problem is no more. Not sure what happened the very first time I tried exactly this. But to confirm, this code compiled and it told me the ti,e is right now, so this part works!
majenko, do you know of any good menu manager framework? I need something to work for my joystick and TFT. This library is close but I think I want simpler, like a linked list of call backs to handle position or something?
Oh, the code that worked:
// Real Time Clock using I2C pins
#include <Wire.h>
#define I2C_DS1307_ADDRESS 0x68
byte bcdToDec(byte val){ return ( (val/16*10) + (val%16) ); }
byte decToBcd(byte val){ return ( (val/10*16) + (val%10) ); }
char date[30];
void getDate( char * buffer ){
Wire.beginTransmission(I2C_DS1307_ADDRESS);
Wire.send(0x00);
Wire.endTransmission();
Wire.requestFrom(I2C_DS1307_ADDRESS, 7);
int second = bcdToDec(Wire.receive());
int minute = bcdToDec(Wire.receive());
int hour = bcdToDec(Wire.receive() & 0b111111); //24 hour time
int weekDay = bcdToDec(Wire.receive()); //0-6 -> sunday - Saturday
int monthDay = bcdToDec(Wire.receive());
int month = bcdToDec(Wire.receive());
int year = bcdToDec(Wire.receive());
//print the date EG 3/1/11 23:59:59
sprintf( buffer, "20%d-%02d-%02d %02d:%02d:%02d", year, month, monthDay, hour, minute, second );
}
void setup(){
Wire.begin();
}
// use getDate(date); and date will have current time in from the sprintf above.
Wed, 04 Sep 2013 00:49:06 +0000
majenko, I just found your RTCC library!
Hmmm, was thinking about writing a DS1307 library, then found your lib, now I'm kind of torn. For a lot of folks, using the Sparkfun RTC is preferred, so they leave their chipKIT board completely alone. If I weren't porting my code over ... and had a crystal, I'd probably just solder it on and use internal RTC. (does it save the time?)
So then I was going to write SFRTC class since it's really just for that product (and I'm not sure all DS1307 use I2C 0x68). I'm thinking if my programs knows what time it is, shouldn't it tell the processor?
Wed, 04 Sep 2013 08:51:06 +0000
The internal RTCC of the PIC32 is alright, but a bit pointless really. There is no facility for a battery backup, so as soon as the chip/board loses power it forgets the time. Great if you're never going to lose power, pointless for all other situations.
I do use the RTCC, but only when I get the actual time from another source (e.g., the internet), or when I just want a regular interrupt with greater accuracy than millis() gives me over a longer period than timers are effective for.
Other than that I use a DS13xx chip typically.
Tue, 25 Feb 2014 21:01:48 +0000
The internal RTCC of the PIC32 is alright, but a bit pointless really. There is no facility for a battery backup, so as soon as the chip/board loses power it forgets the time. Great if you're never going to lose power, pointless for all other situations.
I always thought that a good use would be to get time using NTP then use the rtc module to keep track locally.
Also, I believe some PIC32's have the ability to power the rtc without the processor running but the current draw is so great that you probably still want an external rtc chip.
Jacob
Tue, 25 Feb 2014 21:18:47 +0000
That kind of comes under the heading of "never losing power", in that you're not relying on the RTCC to maintain any functionality while the main power is off, like you would with a real RTC chip.
I mainly use it for longer period alarms, if I want an event to trigger over periods of minutes, or hours, for instance - better than trying to bend a timer into that kind of period, and you don't have to worry about absolute time, only relative.