By continuing to use this site, you agree to our use of cookies. Find out more
Forum sponsored by:
Forum sponsored by Allendale Jan 24th

Arduino programming?

All Topics | Latest Posts

Search for:  in Thread Title in  
Malc26/11/2020 17:26:32
100 forum posts
5 photos

Since my last post on this subject I have had some success with the programming. I have now got the sketch to light all the 4x7 segments in turn and their decimal points. The only trouble is that the sketch is over 200 lines long and I'm sure that there must be a better way of doing this. I have been trying to use arrays to group the "digital write" lines into 0, 1, 2, etc arrays to replace these lines and so shorten the sketch. Am I on the right lines? I will try to post he code here. I think the Arduino forum have grown a little impatient with me so I would be grateful for any suggestions. NB. It seems the post is too long so I will post the sketch in another post.

Malc26/11/2020 17:29:27
100 forum posts
5 photos

Code part 1

// tests a 4x7 seg. disp. with modified blink sketch. displays 0000 1111 2222 3333 etc. with decimal points after all digits.

#define seg //output pins to 7 segment display
#define Don 1000 //delay setting the ON time of segments
#define Doff 250 //delay setting the OFF time of segments


void setup() {
// put your setup code here, to run once:
pinMode(2, OUTPUT); // A segment of display
pinMode(3, OUTPUT); // B segment of display
pinMode(4, OUTPUT); // C segment of display
pinMode(5, OUTPUT); // D segment of display
pinMode(6, OUTPUT); // E segment of display
pinMode(7, OUTPUT); // F segment of display
pinMode(8, OUTPUT); // G segment of display
pinMode(9, OUTPUT); // Decimal Point segment of display
pinMode(10, OUTPUT); // D1 cathode of display
pinMode(11, OUTPUT); // D2 cathode of display
pinMode(12, OUTPUT); // D3 cathode of display
pinMode(13, OUTPUT); // D4 cathode of display
}

void loop()

{

digitalWrite(2, HIGH); // turn the following LEDs (segments) on to display the number 0.
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second.

digitalWrite(2, LOW); //turn the following LEDs (segments)off.
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
digitalWrite(7, LOW);
digitalWrite(9, LOW);

//delay(Doff); // wait for a second.

digitalWrite(3, HIGH); // turn the following LEDs (segnments)on to display the number 1.
digitalWrite(4, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second

digitalWrite(3, LOW); //turn the following LEDs (segments)off.
digitalWrite(4, LOW);
digitalWrite(9, LOW);

// delay(Doff); // wait for a second

digitalWrite(2, HIGH); // turn the following LEDs (segnments)on to display the number 2.
digitalWrite(3, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second

digitalWrite(2, LOW); //turn the following LEDs (segments)off.
digitalWrite(3, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);

//delay(Doff); // wait for a second

digitalWrite(2, HIGH); // turn the following LEDs (segnments)on to display the number 3.
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second

digitalWrite(2,LOW); //turn the following LEDs (segments)off.
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);

//delay(Doff); // wait for a second

digitalWrite(3, HIGH); // turn the following LEDs (segnments)on to display the number 4.
digitalWrite(4, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second

digitalWrite(3,LOW); //turn the following LEDs (segments)off.
digitalWrite(4, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);

// delay(Doff); // wait for a second

digitalWrite(2, HIGH); // turn the following LEDs (segnments)on to display the number 5.
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second

Malc26/11/2020 17:30:58
100 forum posts
5 photos

code part 2

delay(Don); // wait for a second

digitalWrite(2,LOW); //turn the following LEDs (segments)off.
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);

//delay(Doff); // wait for a second

digitalWrite(2, HIGH); // turn the following LEDs (segments) on to display the number 6.
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second

digitalWrite(2, LOW); //turn the following LEDs (segments)off.
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);

//delay(Doff); // wait for a second

digitalWrite(2, HIGH); // turn the following LEDs (segments) on to display the number 7.
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second

digitalWrite(2, LOW); //turn the following LEDs (segments)off.
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(9, LOW);

//delay(Doff); // wait for a second

digitalWrite(2, HIGH); // turn the following LEDs (segments) on to display the number 8.
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second

digitalWrite(2, LOW); //turn the following LEDs (segments)off.
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);

//delay(Doff); // wait for a second

digitalWrite(2, HIGH); // turn the following LEDs (segments) on to display the number 9.
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(7, HIGH);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);

delay(Don); // wait for a second

digitalWrite(2, LOW); //turn the following LEDs (segments)off.
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(7, LOW);
digitalWrite(8, LOW);
digitalWrite(9, LOW);

//delay(Doff); // wait for a second

}

Frances IoM26/11/2020 17:42:28
945 forum posts
27 photos
whenever some 40yrs ago I saw code like that I would immediately look at what I then called table driven code - ie a specialised interpreter + a highly compact bit oriented tables

Edited By Frances IoM on 26/11/2020 17:43:19

duncan webster26/11/2020 18:06:31
avatar
2946 forum posts
34 photos

This is probably rubbish but here goes:

Has Malc actually told us what display he's using? It appears from the code that all 4 digits light up with the same character by just setting the pins 2-9. Is it perhaps a display which has 4 inputs to select which digit is to be driven? If it is then what you have to light up the digits in turn with 25% mark space ratio. There may well be a library to do this for you, when I last did it on a PIC I used someone else's code, but I think the flicker rate is too fast and the brightness is not what it could be.

Malc26/11/2020 18:27:46
100 forum posts
5 photos

Hi Duncan, the display I am using is a 4x7 segment common cathode type (Proto-pic part No. COM-10145). The Arduino pins 10,11, 12, 13 are connected to the D1, D2, D3, D4 cathodes of the 4 digits. The remaining 8 segments are connected to the Arduino pins 2, 3, 4, 5, 6, 7, 8 & 9. All 4 segments do light up at once in the sequence 0000, 1111, 2222, 3333........etc. and then continually repeat. This is exactly what I wanted but in the interests of learning more about programming I am trying to improve the sketch

duncan webster26/11/2020 19:47:47
avatar
2946 forum posts
34 photos

I can't find that part on proto pic website. I can't see in the code where you set the level of 10, 11, 12, 13. The default state is LOW, so I'm presuming that the display is common anode. Your potentially driving 28 LEDs (8888) off the Arduino all at once, which might be close to the limit for output pins (100mA total).

I think this library will do it for you 7 seg but I've not fully read it yet. What you then do is turn pins 10, 11, 12, 13 on and off in sequence to flash the individual characters, do it fast enough and they appear to be all on at the same time.

If you want to do the heavy lifting yourself, as long as you are not using serial comms, you can use pins 0 to 7 (actually 0 to 6 in this case), which makes life easier as pins 0 - 7 are PORTD, and you can set all these pins with one command. PORTD = 0B00111111 will set pins 0 to 6 HIGH and pins 6&7 LOW. This displays '0'. All described at port manip

Malc26/11/2020 20:23:42
100 forum posts
5 photos

Thanks Duncan, that looks like a quest for tomorrow.

duncan webster26/11/2020 20:50:25
avatar
2946 forum posts
34 photos

I think I meant common cathode!

SillyOldDuffer26/11/2020 21:06:31
Moderator
6682 forum posts
1501 photos

Congratulations to Malc:

  • For getting his program to drive the LEDs correctly (a major milestone!)
  • For writing code that's easy to understand. (Rule 1 of programming: Don't leave the reader in the dust!)
  • For recognising 200 lines can probably be compressed and asking advice

I've not tested my version on a real LED so the code is probably buggy, but as an example of a couple of reducing techniques I offer this.

segs1.jpg

seg2.jpg

First trick is to use names rather than numbers in hope the code will be easy to understand in two weeks time, or if some other poor S.O.D. has to debug it.

Second, use a loop. In this example a for loop in setup() sets all the output pins one after the other. The pin numbers happen to be in sequence making a loop easy to apply in this example, but variations of the the same technique can handle non-contiguous pin numbers (Slightly more advanced topic.)

Third, put repeat operations into generalised functions. In this example, setSegments() turns all the LED segments on or off in any combination based on the coded number it's given, and then executes a delay() My example takes advantage of a 7 segment + dp display having 8 control states, which can all be contained in a single integer of type uint8_t (ie an unsigned 8 bit integer.) Also available if more bits are needed: uint16_t, uint32_t and uint64_t)

The encoded command can be written in binary

ABCDEFG.
00000000 // All off
11111111 // All on
11111010 // All on apart from segment E and the decimal point

So a bit set to zero, means 'turn the corresponding segment OFF' and the same bit set to 1 turns it on, (In the Arduino documentation, its explained LOW = 0 and HIGH = 1.) The bits are extracted, or decoded, from group by masking them with a logical and ( & ) , obeying this rule:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

So SEG_A & 0b1000000 = 1, ie HIGH while SEG_A & 0b01111111 = 0, ie LOW

Fourth trick is to overload (technical term) the setSegment() function with a default delay. If 1000mS is wrong, the programmer can override it. So

setSegment( 0xff, 10000 ); // turn all segments and DP ON and wait for 10 seconds

Hope that makes some sense!

Duncan makes a good point about libraries. The very best way to get results in programming is to let someone else to do the hard work! Typically an LED display library would handle several digits by chatting to a control chip, provide dimming, and fonts etc. But it's very educational to start as Malc has done by rolling your own.

Dave

Edit Pesky smileys.

 

Edited By SillyOldDuffer on 26/11/2020 21:10:53

Malc26/11/2020 21:39:24
100 forum posts
5 photos

Many thanks to the two of you for all the effort. I’m going to work my way through all your info and see if my brain is up to it. You should have a bit of peace - it could take me a while. Thanks again, Malc.

duncan webster27/11/2020 03:41:47
avatar
2946 forum posts
34 photos

from the time on this posting you can tell it might be insomniac ramblings:

A somewhat more understandable way of doing what SOD suggests would be to define a set of one dimensional arrays

//int Ch_n[] = {a, b, c, d, e, f, g, dp}

int Ch_0[] = {1, 1, 1, 1, 1, 1, 0, 0};
int CH_1[] = {0, 1, 1, 0, 0, 0, 0, 0};

and so on to

int CH_dp[] = {0, 0, 0, 0, 0, 0, 0, 1};

int Ch_clear[] = {0, 0, 0, 0, 0 , 0, 0, 0}

and then

void setSegments(int Ch_n)
{
digitalWrite(seg_A, Ch_n[0];
digitalWrite(seg_B, Ch_n[1];

and so on to

digitalWrite(seg_dp, Ch_n[7];

and then in loop() call

setSegments(Ch_0);

or whichever you want to send

 

don't forget you can also display A, b, C, d, E, F, H, J, L, S (same as 5), Y

No doubt SOD will put this right if I've erred.

Edited By duncan webster on 27/11/2020 03:51:40

Edited By duncan webster on 27/11/2020 03:52:33

Edited By duncan webster on 27/11/2020 03:55:12

Edited By duncan webster on 27/11/2020 03:55:46

Edited By duncan webster on 27/11/2020 03:56:13

duncan webster27/11/2020 04:12:29
avatar
2946 forum posts
34 photos

And does anyone know what the optimum flash rate would be? if working at 50 hZ it would be 20ms for all 4 digits, 5 ms on, 15ms off for each one.

Malc27/11/2020 08:45:56
100 forum posts
5 photos

Blimey Duncan, sorry if I kept you awake! Looks like I have a busy day ahead, thanks again.Malc.

Roger Hart27/11/2020 09:06:48
135 forum posts
30 photos

Here is the approach I used. not original, pinched off the WEB. Can't remember where.

First a mapping from logical to hardware pin numbers. Then convert a number into an 8 bit wide pattern then bit bang the bit pattern. The convert number part gets around logical anding and testing a 32 bit integer.

// define pin Logical pin / Hardware pin
int pin0 = 0;
int pin1 = 1;
int pin2 = 2;
int pin3 = 3;
int pin4 = 5;
int pin5 = 6;
int pin6 = 7;
int pin7 = 8;


void Send_8_bit(int byt)
{
int d=0;
int binary[8] = {0,0,0,0,0,0,0,0};
{
//convert byt to bit pattern
while (byt>0)
{
binary[d] = byt%2;
byt = byt/2;
d++;
}
// write 8 bits to port pins
if (binary[0]==1) digitalWrite(pin0,HIGH);
else digitalWrite(pin0,LOW);
if (binary[1]==1) digitalWrite(pin1,HIGH);
else digitalWrite(pin1,LOW);
if (binary[2]==1) digitalWrite(pin2,HIGH);
else digitalWrite(pin2,LOW);
if (binary[3]==1) digitalWrite(pin3,HIGH);
else digitalWrite(pin3,LOW);
if (binary[4]==1) digitalWrite(pin4,HIGH);
else digitalWrite(pin4,LOW);
if (binary[5]==1) digitalWrite(pin5,HIGH);
else digitalWrite(pin5,LOW);
if (binary[6]==1) digitalWrite(pin6,HIGH);
else digitalWrite(pin6,LOW);
if (binary[7]==1) digitalWrite(pin7,HIGH);
else digitalWrite(pin7,LOW);
}
}


void setup() {
// set up 8 bit port
pinMode(pin0, OUTPUT);
pinMode(pin1, OUTPUT);
pinMode(pin2, OUTPUT);
pinMode(pin3, OUTPUT);
pinMode(pin4, OUTPUT);
pinMode(pin5, OUTPUT);
pinMode(pin6, OUTPUT);
pinMode(pin7, OUTPUT);
}

void loop() {
// put your main code here, to run repeatedly:

int byt;

byt = 0;

while (byt < 256)
{
Send_8_bit(byt);
byt++;
delay(50);
}
}

Malc27/11/2020 09:38:39
100 forum posts
5 photos

Looks like my days are getting busier. I intend to print out all the replies and code and then see if any of it sinks in, so it could be a while before you hear from me again. Thanks Roger and every one else. Malc.

SillyOldDuffer27/11/2020 10:39:12
Moderator
6682 forum posts
1501 photos

A few comments on Roger's version, not criticisms.

A disadvantage of using an array to hold the segment bits is the amount of memory used and the extra compute power needed to process it. Doesn't matter two hoots on a big computer or a small microcontroller program, but squeezing big programs on to a tiny microcontroller often demands economies.

In Roger's code the statement int binary[8] = {0,0,0,0,0,0,0,0}; allocates 16 bytes of memory, most of which isn't used, whereas

char binary[8] = {0,0,0,0,0,0,0,0}; // allocates 8 bytes of memory

Also, later compilers allow the shorthand:

int binary[8] = {0}; // Zero all 8 elements

Another common compression, Roger uses the form:

if (binary[0]==1) digitalWrite(pin0,HIGH);
else digitalWrite(pin0,LOW);

which can be simplified to:

digitalWrite( pin0, binary[0] ); // Saves a comparison and decision branch.

Malc's version takes up most space but is the easiest to understand. Roger's version saves space, but requires more effort to grasp. Mine may be the most efficient, but it's also the hardest to understand. This is why programming can be hard to learn: fairly clear what Roger's

if (binary[0]==1) digitalWrite(pin0,HIGH);
else digitalWrite(pin0,LOW);

does, whereas digitalWrite( pin0, binary[0] ); is less obvious!

Problem is experienced programmers tend to write harder to understand code because they value machine efficiency and terse expression above basic clarity. In the worst case, they take to writing deliberately obscure code to show how smart they are, which is bad.

Anyway, don't be disheartened if learning to program seems hard. Difficult not because you're stupid, it's because breaking in isn't easy, and early misunderstandings lead to much confusion. It's another riding a bicycle experience; at first impossible, then away you go. Doesn't help that computers and computer languages change much faster than the mechanical world: last year's book may not align properly with this year's compiler, and today's book won't match cleanly with yesterday's computer. Not like a 1930 Adept vs Ketan's latest, where the basic design and operating principles of both lathes are almost identical.

Dave

Ivan Winters27/11/2020 11:08:35
10 forum posts
1 photos

Sorry to be slightly OTS.

I thought there was a version of Arduino that accepted programming in the Python script. Anyone know anything more.

SillyOldDuffer27/11/2020 11:54:56
Moderator
6682 forum posts
1501 photos
Posted by Ivan Winters on 27/11/2020 11:08:35:

Sorry to be slightly OTS.

I thought there was a version of Arduino that accepted programming in the Python script. Anyone know anything more.

Two things you may be remembering:

  • There's a protocol called firmata that allows a Python program running on a PC to control a small Arduino (Uno, Nano etc.). It requires the two computers to be permanently connected, but full Python on the PC can work the Arduino's inputs and outputs as needed for many electronic projects. Basically the big computer makes programming easy while the little one does the dangerous circuit interfacing. RaspberryPi runs firmata, so a permanent pairing could be done relatively cheaply. I guess firmata can't be as fast as a native Arduino C program when speed matters.
  • The more powerful Arduino 32-bit Boards like the Due can run MicroPython, which is a sawn-off subset of grown-up Python. Not tried it myself, though Python and C++ are my favourite languages. There was also a board that ran Linux, but I think is discontinued.

Python can also be installed on the Nucleo / STM range, and other high-end microcontrollers, bigger the better. Also possible to buy microcontrollers pre-loaded with Python or Basic. I've no of experience of them. The problem with Basic and Python is they use a lot of computer resources before the user adds his program. Sluggish and constrained compared with C or C++ too, though that may not matter. Python is heftier than BASIC because it's more advanced, and squeezing it on to a small chip is more of a challenge.

The RaspberryPi runs full Python easily and exposes GPIO pins for electronic projects, but it's electrically delicate compared with most Arduinos, and - being a real computer - rather expensive to build into simple electronic projects.

Dave

Roger Hart27/11/2020 13:51:31
135 forum posts
30 photos

I am a pretty dim programmer and I prefer simple and obvious with just a dash of elegance. Back in the day 'an instruction saved was an instruction earned' when you mapped your program round a disk to keep the speed up.

Those days are gone thankfully, the SAMD21 I usually use has around 32K of data space and some 256K of code space all for a few quid. You can afford to be a bit profligate unless you are trying to squeeze a quart into a pint pot. You can afford obvious, let the machine take the strain. Mercifully the Arduino platform hides the nasty business of handling the ARM peripheral port multiplexer. Other platforms make you see the gory details and strong men/women are known to take fright at the sight.

I like the code improvements from SoD, he points out the tradeoff between obvious/fairly obvious/terse code. Except that I would be tempted to (kindly and respectfully) strangle terse programmers (not really).

Right now I am wrestling with a Python written by some academics who seem to believe writing comments and clear indenting is a mortal sin. Perhaps in academe tab characters and comments cost money - who knows.... Its so bad I even drew a flowchart, not done that for many a year. Snag was I flogged my templates on fleabay years back.

All Topics | Latest Posts

Please login to post a reply.

Magazine Locator

Want the latest issue of Model Engineer or Model Engineers' Workshop? Use our magazine locator links to find your nearest stockist!

Find Model Engineer & Model Engineers' Workshop

Latest Forum Posts
Support Our Partners
emcomachinetools
EngineDIY
cowells
Warco
Eccentric July 5 2018
ChesterUK
Eccentric Engineering
Subscription Offer

Latest "For Sale" Ads
Latest "Wanted" Ads
Get In Touch!

Do you want to contact the Model Engineer and Model Engineers' Workshop team?

You can contact us by phone, mail or email about the magazines including becoming a contributor, submitting reader's letters or making queries about articles. You can also get in touch about this website, advertising or other general issues.

Click THIS LINK for full contact details.

For subscription issues please see THIS LINK.

Digital Back Issues

Social Media online

'Like' us on Facebook
Follow us on Facebook

Follow us on Twitter
 Twitter Logo

Pin us on Pinterest