Offline
Newbie
Karma: 0
Posts: 25
|
 |
« on: April 10, 2012, 06:14:39 pm » |
If the program hangs for any reason, is it likey cto cause any damage to the chip?
I have a system that hands sometimes after around 2000 loops when using the I2C bus, but not writing to it and just using serial, is fine.
If I were to not notice it had hung (for instance coding something else) would it case a problem?
Also as a secondary question, id there a maximum number of times the Arduino can be written to? If so could this be causing it to hang?
|
|
|
|
|
Logged
|
|
|
|
|
Anchorage, AK
Offline
Sr. Member
Karma: 10
Posts: 487
|
 |
« Reply #1 on: April 10, 2012, 06:24:35 pm » |
Do you mean like getting caught in an infinite loop? while (1); No, harmless. This is very close to what happens when you do this: void setup() { // do stuff // do more stuff // do even more stuff }
void loop() {} In this case, loop() will be called, return, then be called again, return again, then be called again... on and on until reset / power-off. Yes, there is a limit to number of flash writes. It's a big number, though. If I remember correctly (too lazy to look it up), it's something like 10,000 or 100,000 writes. I haven't tracked how many times I've uploaded sketches to some of my most active chips, but I'm pretty sure it hasn't been nearly that many.
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX
Online
Faraday Member
Karma: 41
Posts: 5162
CMiYC
|
 |
« Reply #2 on: April 10, 2012, 07:59:10 pm » |
If the program hangs for any reason, is it likey cto cause any damage to the chip? Microcontrollers (and even your computer) very rarely "hangs." Instead it starts executing code in an unexpected path. For example, it is possible for unexpected code to start doing unexpected things to an I/O, which would result in damage. However, the likelyhood is pretty low. So generally "hanging code" isn't damaging. Also as a secondary question, id there a maximum number of times the Arduino can be written to? If so could this be causing it to hang? Yes. Program memory is rated for 10,000 writes while the EEPROM (different memory space) has a 100,000 limit. Consider that writes to program memory can't happen faster than you click upload and that process starts, so worst case you are looking at once per minute. At 10,000 writes, you could corrupt the flash Program Memory in 7 days if you clicked upload once a minute for 24 hours. (See how unlikely this is?) Part of the programming memory is to read back the contents as verification. So if there was a damaged cell, you'd know when the chip was programmed.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 25
|
 |
« Reply #3 on: April 22, 2012, 11:47:02 am » |
Many thanks for the reply, sorry for the delay in getting back to you, ive been busy trying to build a windows to I2C interface to see if it is the display chip thats the problem or the Arduino program.
It turnsout that on the PC, I can send i2c signals all day long with no problem, but with the arduino using my libary Ihave a problem a few times around the loop().
It is often around the 2460th time round.
I have written a simple sketch but not sure if I should put it in here or not.
Jimmy
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 86
Posts: 9360
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #4 on: April 22, 2012, 12:37:39 pm » |
Just post your code and we can help you out. Without the code we can only guess. Please use the #button to get appropiate code tags (its above the smileys 
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 25
|
 |
« Reply #5 on: April 26, 2012, 12:37:06 am » |
Cheers, I never know where to put anything in the forum. First I'll add my libary which I have adapted from the Liquid Crystall Libary MAX6955.h//max6955.h #ifndef Maxim #define Maxim
#include "arduino.h" #include <inttypes.h> #include "Print.h"
class Maxim6955 : public Print { public: Maxim6955(uint8_t address); //constructor void begin(uint8_t test); void clear();
virtual size_t write(uint8_t); using Print::write;
private: void send(uint8_t); //void writeI2C(); uint8_t _address; uint8_t _off; uint8_t _holder; uint8_t _string; uint8_t _d0; uint8_t _d1; uint8_t _d2; uint8_t _d3; uint8_t _d4; uint8_t _d5; uint8_t _d6; uint8_t _d7; };
#endif
MAX6955.cpp//max6955.cpp
#include <stdio.h> #include <string.h> #include <inttypes.h> #include <Wire.h> #include "Arduino.h" #include "max6955.h"
Maxim6955::Maxim6955(uint8_t address) { _address = address; _off = 0x00; }
void Maxim6955::begin(uint8_t testMode) { //start configuring the display Wire.beginTransmission(_address); Wire.write(0x01); // Write to the decode resgister; Wire.write(0b11111111); //decode all digits 1 is decode 0 gives direct access Wire.write(0x01); //Intensity default, guess I should take this from a pin to see where the dash lights are at... Wire.write(0x07); // hex easiest way of seeing which digits to scan (all 8 is 0x07) Wire.write(0x01); // Control Reg 0x01 is shutdown off Wire.endTransmission(); //device setup to accept charectures now, are we doing a display test? if(testMode == 1) { //test is wanted, this lightsup all segments for 1.5 seconds then turns off Wire.beginTransmission(_address); Wire.write(0x07); //TestRegister Wire.write(0x01); //Turn it on Wire.endTransmission(); delay(1500); //delay 1.5 seconds Wire.beginTransmission(_address); Wire.write(0x07); //TestRegister Wire.write(_off); //Turn it off Wire.endTransmission(); } else { Wire.beginTransmission(_address); Wire.write(0x07); //TestRegister Wire.write(_off); //Turn it off Wire.endTransmission();
} //end test; } //END BEGIN
/******************* High Level commands */
void Maxim6955::clear() { //manual function to clear display _d0 = 32; //space char _d1 = 32; //space char _d2 = 32; //space char _d3 = 32; //space char _d4 = 32; //space char _d5 = 32; //space char _d6 = 32; //space char _d7 = 32; //space char Wire.beginTransmission(_address); Wire.write(0x20); //TestRegister Wire.write(_d0); //"space" Char Wire.write(_d1); //"space" Char Wire.write(_d2); //"space" Char Wire.write(_d3); //"space" Char Wire.write(_d4); //"space" Char Wire.write(_d5); //"space" Char Wire.write(_d6); //"space" Char Wire.write(_d7); //"space" Char Wire.endTransmission(); }
inline size_t Maxim6955::write(uint8_t value) { send(value); return 1; // assume sucesss }
// Send to a string void Maxim6955::send(uint8_t value) { _d0 = _d1; _d1 = _d2; _d2 = _d3; _d3 = _d4; _d4 = _d5; _d5 = _d6; _d6 = _d7; _d7 = value; //_holder = value;
Wire.beginTransmission(_address);
Wire.write(0x20); Wire.write(_d0); Wire.write(_d1); Wire.write(_d2); Wire.write(_d3); Wire.write(_d4); Wire.write(_d5); Wire.write(_d6); Wire.write(_d7);
Wire.endTransmission(); }
now the sketch //max6955.ino
#include <Wire.h> #include <max6955.h>
Maxim6955 max1(0x60); int x = 0;
void setup() { max1.begin(1); }
void loop() { max1.clear(); //delay(500); max1.print(x); x++; delay(1000); //Serial.println(x); }
The same also happens if I do not use my libary and insted just send the I2C data by using the following ////////////////////////////////////////////////////////////////// // The inner workings of the golem... // brightness pin 2 on arduino // TMP36 on Pin A0 ///////////////////////////////////////////////////////////////// #include <Wire.h>;
int x = 0; // count the loops to see if we get a hang
int mode = 0; // Default mode theat the system boots up in
int testOff = 0; // for some reason will not let me reite 0x00 tot he system so define it here int digit0 = 32; // "space char as default - blank digit on boot" int digit1 = 32; // "space char as default - blank digit on boot" int digit2 = 32; // "space char as default - blank digit on boot" int digit3 = 32; // "space char as default - blank digit on boot" int digit4 = 32; // "space char as default - blank digit on boot" int digit5 = 32; // "space char as default - blank digit on boot" int digit6 = 32; // "space char as default - blank digit on boot" int digit7 = 32; // "space char as default - blank digit on boot" byte numbers[10]; //array to hold the numbers in , not sure It i will need
int max1 = 0x60; //address of first max6955 chip
int brightness = 0x0D; //original brightness level int tempPin = A0;
////////////////////////////////////////////////////////////////// // MAX6955 REGISTERS //////////////////////////////////////////////////////////////////
int regDecode = 0x01; int regIntens = 0x02; int regScan = 0x03; int regConfig = 0x04; int regTest = 0x07;
////////////////////////////////////////////////////////////////// // END REGISTER SETUP //////////////////////////////////////////////////////////////////
void setup() { pinMode(2, INPUT); //pinMode(tempPin, INPUT); Serial.begin(9600); Wire.begin(0x00); wireSetup(); show(); //sends initial chars to the display //setup nuumbers numbers[0] = 48; numbers[1] = 49; numbers[2] = 50; numbers[3] = 51; numbers[4] = 52; numbers[5] = 53; numbers[6] = 54; numbers[7] = 55; numbers[8] = 56; numbers[9] = 57; numbers[0] = 48; Serial.println("End Setup"); //for debug, lets me know when its free. }
void loop() { /////////////// count demo//////////////////// for(int x=0; x<10000; x++){ if(x<10) { digit0 = numbers[0]; digit1 = numbers[0]; digit2 = numbers[0]; digit3 = numbers[x]; } else if(x<100) { digit0 = numbers[0]; digit1 = numbers[0]; digit2 = numbers[x / 10]; digit3 = numbers[x % 10]; } else if(x<1000) { digit0 = numbers[0]; digit1 = numbers[x / 100]; digit2 = numbers[(x % 100)/10]; digit3 = numbers[x % 10]; } else if(x<10000) { digit0 = numbers[x / 1000]; digit1 = numbers[(x % 1000)/100]; digit2 = numbers[(x % 100)/10]; digit3 = numbers[x % 10]; } show(); delay(50); }
//////END COUNT DEMO ???????????????????? } //end loop
void show() { Wire.beginTransmission(max1); Wire.write(0x02); Wire.write(brightness); Wire.endTransmission(); Wire.beginTransmission(max1); Wire.write(0x20); Wire.write(digit0); Wire.write(digit1); Wire.write(digit2); Wire.write(digit3); Wire.write(digit4); Wire.write(digit5); Wire.write(digit6); Wire.write(digit7); Wire.endTransmission(); //////////////////////// // serial debug // //////////////////////// Serial.print(char(digit0)); Serial.print(char(digit1)); Serial.print(char(digit2)); Serial.print(char(digit3)); Serial.print(char(digit4)); Serial.print(char(digit5)); Serial.print(char(digit6)); Serial.println(char(digit7)); ///////////////////////// // end serial debug // ///////////////////////// }
void wireSetup() { Wire.beginTransmission(max1); Wire.write(regTest); Wire.write(0x01); Wire.endTransmission(); delay(1500); Wire.beginTransmission(max1); Wire.write(regTest); Wire.write(testOff); Wire.endTransmission(); Wire.beginTransmission(max1); Wire.write(regDecode); Wire.write(0b11111111); //decode all digits 1 is decode 0 gives direct access Wire.write(0x01); //Intensity default, guess I should take this from a pin to see where the dash lights are at... Wire.write(0x07); // hex easiest way of seeing which digits to scan (all 8 is 0x07) Wire.write(0x01); // Control Reg 0x01 is shutdown off Wire.endTransmission(); }
Any help would be greatly apprechiated. I have narrowed it down to the arduino, and the fact that it hangs / stops says to me its running out of ram, if I reset the arduino (withouth disturbing the power supply), it will start from the beggining, so it appears not to be the display chip. Finally, if I enable the serial output, it stops sending serial data when it hangs also. Many thanks Jimmy
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 311
Posts: 35470
Seattle, WA USA
|
 |
« Reply #6 on: April 26, 2012, 09:23:36 am » |
int x = 0; // count the loops to see if we get a hang
int mode = 0; // Default mode theat the system boots up in
int testOff = 0; // for some reason will not let me reite 0x00 tot he system so define it here int digit0 = 32; // "space char as default - blank digit on boot" int digit1 = 32; // "space char as default - blank digit on boot" int digit2 = 32; // "space char as default - blank digit on boot" int digit3 = 32; // "space char as default - blank digit on boot" int digit4 = 32; // "space char as default - blank digit on boot" int digit5 = 32; // "space char as default - blank digit on boot" int digit6 = 32; // "space char as default - blank digit on boot" int digit7 = 32; // "space char as default - blank digit on boot" None of these need to be ints. In fact, most of them look like they should be chars. In any case, I don't see a huge amount of SRAM being consumed. I'd look elsewhere for the problem, like a failure to communicate between the Arduino and the I2C device - like a Wire function waiting forever.
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX
Online
Faraday Member
Karma: 41
Posts: 5162
CMiYC
|
 |
« Reply #7 on: April 26, 2012, 11:30:56 am » |
Finally, if I enable the serial output, it stops sending serial data when it hangs also. Which is where?
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 25
|
 |
« Reply #8 on: April 26, 2012, 11:53:05 pm » |
None of these need to be ints. In fact, most of them look like they should be chars.
No problem - I'll change these over and report back I'd look elsewhere for the problem, like a failure to communicate between the Arduino and the I2C device - like a Wire function waiting forever.
That is possible, so how would I find this, first instinct would be to add a Serial.print() in the library for Wire, but while I was writing my own I could not fathom how to get this to work, but will see what I can do. Finally, if I enable the serial output, it stops sending serial data when it hangs also. Which is where? in the show() command of the 2nd example there is the block of //////////////////////// // serial debug // //////////////////////// Serial.print(char(digit0)); Serial.print(char(digit1)); Serial.print(char(digit2)); Serial.print(char(digit3)); Serial.print(char(digit4)); Serial.print(char(digit5)); Serial.print(char(digit6)); Serial.println(char(digit7)); ///////////////////////// // end serial debug // /////////////////////////
I may have been better describing it as ther serial debug hangs. Many thanks for the feedback so far though and any further ideas welcomed. Once I get this sorted, I can make some real progress with the project. Jimmy
|
|
|
|
« Last Edit: April 27, 2012, 12:57:35 am by manicmoddin »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 25
|
 |
« Reply #9 on: April 27, 2012, 01:47:15 am » |
That is possible, so how would I find this, first instinct would be to add a Serial.print() in the library for Wire, but while I was writing my own I could not fathom how to get this to work, but will see what I can do. ok, I have had a quick look through the twi.c file and found the function twi_writeTo() This returns a number depending on what its sucsess is: * Output 0 .. success * 1 .. length to long for buffer * 2 .. address send, NACK received * 3 .. data send, NACK received * 4 .. other twi error (lost bus arbitration, bus error, ..) on my serial out I got a 4 when it hangs, so this is a problem with the bus then? so either my wires, breadboard or the connections in the Arduino / max breakout board I think. I have twisted the data and the clock wires together to hopefully cancel out interferance, but this dont seem to work, other than soldering to the boards, I'm at a loss as to a better option.
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX
Online
Faraday Member
Karma: 41
Posts: 5162
CMiYC
|
 |
« Reply #10 on: April 27, 2012, 02:03:31 pm » |
What size pull-up resistors on the I2C lines?
|
|
|
|
|
Logged
|
|
|
|
|
Anchorage, AK
Offline
Sr. Member
Karma: 10
Posts: 487
|
 |
« Reply #11 on: April 27, 2012, 02:24:58 pm » |
Twisting wires together doesn't cancel interference unless those two wires carry equal-but-opposite signals that are fed to a balanced input. AFAIK, it can only hurt as the signals may then couple to each other. Also, I would refactor your module like so: char data[8]; // Forget _d0-_d7
uint8_t Maxim6955::write(uint8_t chr) { Wire.beginTransmission(_address); Wire.write(0x20); // Shift values back one digit, writing along the way to save a second loop for (uint8_t i = 1; i < 8; i++) { Wire.write(data[i]); data[i-1] = data[i]; } // Shift in new char and write it data[7] = chr; Wire.write(chr); Wire.endTransmission(); // Return an error code if you have one... return (TWI_error_code); }
// Print C-style strings uint8_t Max6955::print(char *str) { uint8_t i = 0; uint8_t ret;
// Loop through C-style string and write each char while (str[i] != 0x00) { ret = write(str[i]); if (ret != 0) break; } // Pass along any errors return ret; }
// Overload print for C++ strings uint8_t Max6955::print(String str) { // Loop through string chars one at a time, calling write(char) for each // Return error code from write(char) if != 0 }
// You may wish to overload print for ints, floats, etc. Up to you.
// Call print with 8 spaces uint8_t Max6955::clear() { return print(" "); } I'm a C guy, so I'm not totally up to speed on C++ .. at least, the finer details of classes. I'm halfway through a book, but not ready to write my own code here, so you'll have to fill in the details on the C++ String handling, and any errors I made on calling conventions within a namespace.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 25
|
 |
« Reply #12 on: April 29, 2012, 12:58:06 pm » |
What size pull-up resistors on the I2C lines?
These are using 4.7K ohm as per the datasheet, so stumped on that. Twisting wires together doesn't cancel interference unless those two wires carry equal-but-opposite signals that are fed to a balanced input. AFAIK, it can only hurt as the signals may then couple to each other. Also, I would refactor your module like so: char data[8]; // Forget _d0-_d7
uint8_t Maxim6955::write(uint8_t chr) { Wire.beginTransmission(_address); Wire.write(0x20); // Shift values back one digit, writing along the way to save a second loop for (uint8_t i = 1; i < 8; i++) { Wire.write(data[i]); data[i-1] = data[i]; } // Shift in new char and write it data[7] = chr; Wire.write(chr); Wire.endTransmission(); // Return an error code if you have one... return (TWI_error_code); }
// Print C-style strings uint8_t Max6955::print(char *str) { uint8_t i = 0; uint8_t ret;
// Loop through C-style string and write each char while (str[i] != 0x00) { ret = write(str[i]); if (ret != 0) break; } // Pass along any errors return ret; }
// Overload print for C++ strings uint8_t Max6955::print(String str) { // Loop through string chars one at a time, calling write(char) for each // Return error code from write(char) if != 0 }
// You may wish to overload print for ints, floats, etc. Up to you.
// Call print with 8 spaces uint8_t Max6955::clear() { return print(" "); } I'm a C guy, so I'm not totally up to speed on C++ .. at least, the finer details of classes. I'm halfway through a book, but not ready to write my own code here, so you'll have to fill in the details on the C++ String handling, and any errors I made on calling conventions within a namespace. Many thanks I will try with untwisted wires and get back, if it makes a differnece, with regards to the code, it makes little sence to me, I wrote that a while ago, over a coupke of days of bodging some together, will give it a try though and see if it helps  Jimmy
|
|
|
|
|
Logged
|
|
|
|
|
|