Author Topic: Arduino code compiles but doesn't do anything  (Read 5684 times)

0 Members and 1 Guest are viewing this topic.

Offline raspberrypiTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 358
  • Country: us
Re: Arduino code compiles but doesn't do anything
« Reply #25 on: March 10, 2017, 04:27:45 am »
I made another thread in case someone else need to search this site. With some more questions in it.
So I added a "nine" to the code and it worked but I don't think it was done properly.

Oops I deleted the link to the new thread, but anyway its in this same sub forum.
That actually makes it worse for anyone searching the site because they are unlikely to find all the topics you have made about different pieces of the same problem.  IMHO its best not to start a new topic unless you have started a new project or there is some other clear and total break from the subject of the previous topic.

Your new topic is: https://www.eevblog.com/forum/microcontrollers/seven-seg-disp-program-for-arduino-how-to/

The code I just posted should handle adding '9' (or even 'A'-'F') easily - just edit the for loop in loop() to let it count higher.
e.g.
Code: [Select]
   for(char i=1; i<=9; i++){
Its probably easier to continue the discussion here . . .

It seems like you guys think I know more then I actually do. I had no idea what "C" was (other then it was computer programing language) until the day before yesterday, so when I read your posts I have to have google and wikipedia open to figure out what you are talking about, incredibly challenging which is good, but almost to the point where its seems overwhelming. I thought the arduino IDE code was something just for playing with the arduino. I learn fast but not that fast! So I have no idea what that syntax means besides ; is like a period.
I'm legally blind so sometimes I ask obvious questions, but its because I can't see well.
 
The following users thanked this post: tooki

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12807
Re: Arduino code compiles but doesn't do anything
« Reply #26 on: March 10, 2017, 04:41:39 am »
Let me throw a link at you: A free online book introducing C.  It assumes you have *some* programming experience in another high level procedural language.
'The C Book' (2nd ed.) by Mike Banahan, Declan Brady and Mark Doran

It covers C89 which is fairly close to C99 which is for most purposes a subset of C++ which underlies the Arduino programming language.  The only C99'ism I have used above is declaring loop variables at point of use inside the for() statement.  Everything else is covered in 'The C Book' or in the reference section of the official Arduino site.

Subject to time constraints, I am quite happy to answer questions about my code, line by line or even expression by expression.
 

Offline alsetalokin4017

  • Super Contributor
  • ***
  • Posts: 2055
  • Country: us
Re: Arduino code compiles but doesn't do anything
« Reply #27 on: March 10, 2017, 06:01:21 am »
I really appreciate the effort in the replies, but I copied and pasted this code as I'm still not at the point to write it. I almost understand the code but I'm missing something. Basically I just do trial and error as I till haven't found a good resource that explains these codes line by line.
Good code shouldn't need explaining line by line - one comment every five or ten lines should be sufficient, + a block comment explaining the parameters and purpose for each function.

OTOH crap code can still be difficult for an experienced programmer to understand with a comment on each line.  The comments frequently add to the confusion,  as if a programmer is too stupid and lazy to learn how to write better code, they are usually also too lazy to keep the comments up to date when they change the code.  You *CANNOT* learn to program effectively by copying a stupid+lazy programmer.

Also, I believe that beginners should be introduced to good coding patterns like named constants in place of 'magic numbers' and abstraction and looping in place of repetition ('Rule of three') as soon as possible - certainly by the time they've played with the basic example sketches and learnt about the C for loop.

One of the things I dislike about the Arduino libraries is that they hide the fact that the MCU's I/O pins are actually grouped into ports.  If you are using another MCU the first step would be to find 7 pins for your segment lines, ideally all in sequence on the same port.  Then you'd code a bit pattern for each digit you need to display, and write code to transfer that bit pattern from an array, directly to the port the segment lines are on.   It would be possible to split the lines across more than one port, but there is a strong disincentive to do so, because separating out the bits from the segment pattern and rearranging them to match the port bits the segment lines are actually hooked to, wastes code space and processing time.

Another thing I don't like about Arduinos is the tendency to use integer variables for named numeric constants.  If your widgit is on pin 7, the name you refer to it by should be a constant, as the pin cant be changed without rewiring, and ideally it should be a literal constant (#define or enum) so the compiler can better optimise it.

Given the limitations of the Arduino HAL, here's how I'd code it to maximise the amount of it I can reuse if I want to add more digits with multiplexing, or use a starburst display to support text.
Code: [Select]
#include <avr/pgmspace.h> // for PROGMEM - see [url]https://www.arduino.cc/en/Reference/PROGMEM[/url]

//Pin mappings for segments in order: abcdefg dp
const PROGMEM char SegPin[]={7,6,5,11,10,8,9,4};

//Display type, (uncomment one only)
enum {SEG_OFF=0,SEG_ON};  // Common Cathode
//enum {SEG_ON=0,SEG_OFF};  // Common Anode

//Map segment names to position in SegPin
enum {SEG_A=0,
      SEG_B,
      SEG_C,
      SEG_D,
      SEG_E,
      SEG_F,
      SEG_G,
      SEG_DP};

typedef unsigned char segbit_t;  //Change this for displays
// with more than 8 segments, and provide a new font array.

// C source for 7 segment HEX font
// Bit patterns entered in normal
// segment order: abcdefg
const PROGMEM segbit_t Seg7font[]={
    0b1111110, // '0'
    0b0110000, // '1'
    0b1101101, // '2'
    0b1111001, // '3'
    0b0110011, // '4'
    0b1011011, // '5'
    0b1011111, // '6'
    0b1110000, // '7'
    0b1111111, // '8'
    0b1110011, // '9'
    0b1110111, // 'A'
    0b0011111, // 'B'
    0b1001110, // 'C'
    0b0111101, // 'D'
    0b1001111, // 'E'
    0b1000111, // 'F'
    0b0000000  // blank
};
// End Font
enum {NSEGS=sizeof(SegPin)/sizeof(SegPin[0])}; // Because the
// Arduino IDE mangles sizeof() if I use it directly in a function

enum {SEGAMASK=0b1000000}; // mask for first segment bit

enum {BLANK=16}; // Must match index of blank in font array


/*********************************
* init7seg: Set all segment pins *
* as outputs and turn them off.  *
*********************************/
void init7seg(void){

    for(char i=0; i<NSEGS; i++) {
        digitalWrite(SegPin[i],SEG_OFF);
        pinMode(SegPin[i],OUTPUT);
    }
}

/************************************
* write7seg(n): Outputs the segment *
* pattern for n to the display. n's *
* range is 0 to 15, for 0-9, A-F    *
* or BLANK for display off.         *
************************************/
// Hardcoded unrolled 7 segment version
void write7seg(char n){

// Bitwise black magic to extract a segment bit from
// a font pattern to simplify the unrolled loop.
// 0x40 is the bitmask for segment a, b is 1 bit lower etc.
#define SEGBIT(pattern,bn) ((pattern&(SEGAMASK>>bn))?SEG_ON:SEG_OFF)

// and to simplify outputting the bits
#define OUTSEG(s) digitalWrite(SegPin[s],SEGBIT(Seg7font[n],s))

    // Finally output segments a-g
    OUTSEG(SEG_A);
    OUTSEG(SEG_B);
    OUTSEG(SEG_C);
    OUTSEG(SEG_D);
    OUTSEG(SEG_E);
    OUTSEG(SEG_F);
    OUTSEG(SEG_G);
}
// Finished with the macros
#undef SEGBIT
#undef OUTSEG

/* --- commented out ---
// Slow but easier to understand loop version
void write7seg(char n){
   segbit_t mask=SEGAMASK;

    for(char s=SEG_A; s<=SEG_G; s++){

        // Extract a segment bit from the font for character n
        if(Seg7font[n]&mask){

        // and output it to the corresponding pin     
            digitalWrite(SegPin[s],SEG_ON);
        }else{
           digitalWrite(SegPin[s],SEG_OFF);
        }

    mask>>=1; // Shift to next segment position
    }
}
--- end comment out --- */

// No main() we are in Arduino-land :(

/****************
* Arduino setup *
*****************/
void setup(void){
    init7seg();
}

/***************
* Arduino loop *
****************/
void loop(void){
   
   // Display numbers 1-8
   for(char i=1; i<=8; i++){
       write7seg(i);
       delay(2000); // for two seconds each.
   }
}
I've checked it compiles OK but haven't tested it on actual hardware.
I'm using enums where I would normally use #defines, because I need a lot of consecutive numeric constants.    The two #defines in the unrolled version of write7seg() are to give the compiler the best possible chance of optimising the segment output routine to a simple sequence of calls to digitalWrite()a single bit (SEG_ON or SEG_OFF) to a fixed pin. 

N.B. I am a C programmer. not a C++ one though I can 'hum the tune' if I have to.  On a small 8 bit MCU, you have to be very aware of how much work the processor is going to have to do to execute a particular line of code or how much space a definition will use up.
An experienced desktop C++ programmer would think my code stinks, but when considered as embedded C its actually fairly clean.

Sorry... but your code doesn't actually work (for me). I've got the hardware setup as described using Arduino ProMini and CC display, and both the OP's original code (modified for CC display and my own pin mappings) and the random number generator code I posted earlier DO work on my hardware, but your code doesn't. Yes, I've inserted my own pin mappings.  Your code very very dimly lights up two segments of the display (e and f I think) and just sits there for several seconds, then goes out for a brief time then relights, very very dimly, the same two segments.

Let's face it: your code shows some sophisticated programming, but it is pitched way higher than the OP is ready to absorb. Plus... it doesn't work. And from my own rudimentary level of programming (I did get the joke about the best FORTRAN programs written after dropping the stack of cards) I can't figure out why it doesn't or how to change it so that it does.

Some people might take the position that "crap" code that works is actually better than sophisticated "proper" code that doesn't work.
« Last Edit: March 10, 2017, 06:04:09 am by alsetalokin4017 »
The easiest person to fool is yourself. -- Richard Feynman
 
The following users thanked this post: Ian.M

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12807
Re: Arduino code compiles but doesn't do anything
« Reply #28 on: March 10, 2017, 06:22:45 am »
Sorry... but your code doesn't actually work (for me). I've got the hardware setup as described using Arduino ProMini and CC display, and both the OP's original code (modified for CC display and my own pin mappings) and the random number generator code I posted earlier DO work on my hardware, but your code doesn't. Yes, I've inserted my own pin mappings.  Your code very very dimly lights up two segments of the display (e and f I think) and just sits there for several seconds, then goes out for a brief time then relights, very very dimly, the same two segments.

Let's face it: your code shows some sophisticated programming, but it is pitched way higher than the OP is ready to absorb. Plus... it doesn't work. And from my own rudimentary level of programming (I did get the joke about the best FORTRAN programs written after dropping the stack of cards) I can't figure out why it doesn't or how to change it so that it does.

Some people might take the position that "crap" code that works is actually better than sophisticated "proper" code that doesn't work.
Thanks for running it on real hardware.   You are right that working code is better than apparently elegant but broken code.  It looks like I'll have to grab an Arduino and a breadboard and dig into it and fix it now :-[  |O

While you've got it set up, if you've got the time, please try commenting out the hardcoded unrolled version of write7seg() and uncommenting the slow loop version as the odds are fairly high I've FUBARed the unrolled version.
 

Offline alsetalokin4017

  • Super Contributor
  • ***
  • Posts: 2055
  • Country: us
Re: Arduino code compiles but doesn't do anything
« Reply #29 on: March 10, 2017, 07:34:02 am »
I'll try, but it's past my bedtime so I may not get to it until tomorrow.

Thanks for your advice and patience; I'm "not a programmer" nor do I play one on TV. I learned that I am not a programmer when my computer science teacher way back in the IBM 360 day took a 150 card FORTRAN program I had written and wrote a one-line APL function that did the same thing.    :palm:
The easiest person to fool is yourself. -- Richard Feynman
 
The following users thanked this post: Ian.M, tooki

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12807
Re: Arduino code compiles but doesn't do anything
« Reply #30 on: March 10, 2017, 08:45:24 am »
Scrap that request.  It was a bad use of PROGMEM.  Delete the whole line:
Code: [Select]
#include <avr/pgmspace.h> // for PROGMEMand the keyword PROGMEM from the pinmapping line:
Code: [Select]
const PROGMEM char SegPin[]={7,6,5,11,10,8,9,4};and also from the 'font' line:
Code: [Select]
const PROGMEM segbit_t Seg7font[]={
I'm too used to Microchip's C18 where the ROM qualifier works the way I thought PROGMEM did, and XC8 where const is overloaded to mean ROM. :( Apparently you have to use special macros under AVR GCC to fetch data from PROGMEM so my code was using garbage pin numbers and segment patterns.  |O

After the above fix, I've tested it on a genuine Uno with the O.P.s original pin mapping to a LTS7760R single digit common cathode display (with 330R resistors in each segment line) and it now works flawlessly.  I also tested the commented out loop version.

I'm correcting the original post to avoid confusion.

Edit: Replaced attached sketch. Removed some debug printf() statements from the commented out loop version of write7seg(). Changed to use #if 1 or #if 0 instead of commenting out code.
--
'Air Code' is the programmer's equivalent of 'Air Guitar' but is a *LOT* more embarrassing ;-)
« Last Edit: March 10, 2017, 09:41:09 am by Ian.M »
 

Offline alsetalokin4017

  • Super Contributor
  • ***
  • Posts: 2055
  • Country: us
Re: Arduino code compiles but doesn't do anything
« Reply #31 on: March 10, 2017, 03:15:08 pm »
Yes, that fixed it here too (Chinese ProMini clone w/ optiboot). Thanks for revising!

 :-+
« Last Edit: March 10, 2017, 03:17:00 pm by alsetalokin4017 »
The easiest person to fool is yourself. -- Richard Feynman
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9886
  • Country: us
Re: Arduino code compiles but doesn't do anything
« Reply #32 on: March 10, 2017, 04:08:52 pm »
I'll try, but it's past my bedtime so I may not get to it until tomorrow.

Thanks for your advice and patience; I'm "not a programmer" nor do I play one on TV. I learned that I am not a programmer when my computer science teacher way back in the IBM 360 day took a 150 card FORTRAN program I had written and wrote a one-line APL function that did the same thing.    :palm:

APL was amazing for those who could wrap their head around it.  OTOH, Fortran is still alive and well!
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12807
Re: Arduino code compiles but doesn't do anything
« Reply #33 on: March 10, 2017, 05:10:52 pm »
AAgHH!!! the pain of using Arduino Serial.print(whatever) for debugging  |O :palm:
It takes FOUR statements to display two labelled variables on the same line! 
Code: [Select]
Serial.print("A="); Serial.print(a,DEC); Serial.print("   B="); Serial.println(b,BIN);WTF were the Arduino software guys thinking when they left out printf()?  :-//  :--

To find the above bug, I ended up wrapping the header for the raw AVR serial stdio stream code I wrote a few days ago in extern "C" { .... }; just so I could use printf() for debugging.   >:(
 

Online bingo600

  • Super Contributor
  • ***
  • Posts: 1977
  • Country: dk
Re: Arduino code compiles but doesn't do anything
« Reply #34 on: March 10, 2017, 06:26:14 pm »
AAgHH!!! the pain of using Arduino Serial.print(whatever) for debugging  |O :palm:
It takes FOUR statements to display two labelled variables on the same line! 
Code: [Select]
Serial.print("A="); Serial.print(a,DEC); Serial.print("   B="); Serial.println(b,BIN);WTF were the Arduino software guys thinking when they left out printf()?  :-//  :--


Just use sprintf , and "Arduino print" the resulting string

/Bingo
 

Offline sleemanj

  • Super Contributor
  • ***
  • Posts: 3020
  • Country: nz
  • Professional tightwad.
    • The electronics hobby components I sell.
Re: Arduino code compiles but doesn't do anything
« Reply #35 on: March 11, 2017, 08:57:38 am »

WTF were the Arduino software guys thinking when they left out printf()?  :-//  :--

They were thinking that bringing in printf means an absolute ton of code on a flash and ram limited device so it's better not to promote it's use :-)

As above, sprintf (or better snprintf) is in the standard avr libc (as is printf for that matter, but what they define as "stdout" I have no idea), so feel free to use it to format your string, if you have the room to spare.
~~~
EEVBlog Members - get yourself 10% discount off all my electronic components for sale just use the Buy Direct links and use Coupon Code "eevblog" during checkout.  Shipping from New Zealand, international orders welcome :-)
 

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12807
Re: Arduino code compiles but doesn't do anything
« Reply #36 on: March 11, 2017, 10:10:41 am »
They were thinking that bringing in printf means an absolute ton of code on a flash and ram limited device so it's better not to promote it's use :-)
The lightweight stream.print() and stream.println() methods are of course the preferred option for your application code, - and explicitly managing the buffer for snprintf() if you use it is the sane thing to do, - but rather than discouraging use by making it incredibly difficult to add a printf() method cleanly to the serial class, IMHO they should have provided it but tagged with __attribute__((deprecated)) so it raises a warning if used.

As above, sprintf (or better snprintf) is in the standard avr libc (as is printf for that matter, but what they define as "stdout" I have no idea), so feel free to use it to format your string, if you have the room to spare.

Avr libc doesn't initialise the stdio streams - fair enough on an embedded system as there's no knowing what peripheral they should be connected to - so you have to set them up yourself.  That was fairly easy to my quick&dirty blocking UART putchar() and getchar(), but getting them hooked cleanly to an Arduino I/O stream class is a little trickier.

 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf