Use of PORTD instead of DigitalWrite

Hi,

I have a little clock project but want to update the code so you don’t see any flashing of the code. One of the things I could do is change digitalWrite() to PortD B00100001

But I have some problems:

I use 4 LEDS (digital port nr 2,3,4 and 5) and 4 buttons (6,7,8 and 9)

When I use PortD, there are strange things happens with my buttons, could anyone explain me this and give a solution?

thx

#include <Wire.h>           //http://arduino.cc/en/Reference/Wire
#include <Time.h>           //http://playground.arduino.cc/Code/Time
#include <DS3232RTC.h>        //http://github.com/JChristensen/DS3232RTC

byte newMinute = 99; 
const byte LEDs[] = {2, 3, 4, 5};

tmElements_t tm; 

void setup() { 
  Wire.begin();
  Serial.begin(9600);

  setSyncProvider(RTC.get);   // the function to get the time from the RTC
 
   for (byte i=0; i< 4; i++) {
   pinMode (LEDs[i], OUTPUT); 
   
     for (byte i=0; i< 4; i++) {
    pinMode (i + 6, INPUT_PULLUP);
  }
  }
  
}

void loop() {
 
 
   if (digitalRead(9) == LOW) {
    newMinute = 99;
    Serial.println("ButtonPushed");
  PORTD = B00000000;
    }else{
    
    
    
  if (!RTC.read(tm)) { 
  
    time_t t = now();
    int iMinute = minute(t);

    
    if (newMinute != iMinute ) { 
        Serial.println(iMinute);
    newMinute = iMinute;  //Set newMinute to the new value
    int y = 2;
    int test;
       
     for (int i=2; i <= (iMinute % 5)+1 ; i++){
         y = 2 * y;
         test = test + y;
      }  
      PORTD = test;
    }
    
  }  
  }
}

you should only change the bits in PORTD to which the LEDs are connected, not all of them.

That means you have to do something like

PORTD = PORTD | 0b00010000; to set a single bit without affecting the others

PORTD = PORTD & 0b11101111; to clear a single bit ...

Similar to the ++ operator, the compiler allows
a = a | b
a = a & b

To be reduced to
a |= b
a &= b

You don't need to update clock output very often. There should be no flashing if digitalWrite() is used properly - it may be slow compared with port manipulation but that "slow" is a number of microseconds.

...R

Ok,

I changed

  PORTD = test; into PORTD = PORTD | test;

but when I now press the button, it keeps printing "buttonPushed" to the serial for the rest of the minute....

I have a little clock project but want to update the code so you don't see any flashing of the code.

Can you please post your original code that shows the flashing ? I can't help feeling that there is an easier way to solve the problem rather than writing to PORTD.

That is my code…

I am just started… If it doesn’t work with 4 leds, how can it work with 100 of them???

I’m just looking for a fast way to turn the LEDs oON or OFF…

When do something like this:

  • turn off all the leds
  for(int i=2;i<6;i++)
  digitalWrite(i,LOW);
  • turn on the right LEDs
  for (int i=1; i <= (newMinute % 5); i++){
          digitalWrite(i+1,HIGH);
        }

you see a little flash for example if the previous minute was 3 and the new minute 4

When I suggested that you post your code I actually meant all of it, not snippets. A circuit diagram would be handy too.

If you want to avoid seeing flashes when changing minutes why not leave the LEDs on and just turn on the new one ?

UKHeliBob:
When I suggested that you post your code I actually meant all of it, not snippets. A circuit diagram would be handy too.

The code is in my first post...

UKHeliBob:
If you want to avoid seeing flashes when changing minutes why not leave the LEDs on and just turn on the new one ?

just turn the new leds??

0 minutes = 0 leds
1 minutes = led 1
2 minutes = led 1 & led 2
3 minutes = led 1, led 2 & led 3
4 minutes = led 1, led 2, led 3 and led 4
5 minues = 0 leds

that's why the minutes%5 is for

so when you go from 4 to 5 minutes (for example) no leds to turn on...

The code is in my first post.

Is that not the code using PORTD ? I meant your original code using digitalWrite()

just turn the new leds??

Yes, if there are any to be turned on. At the moment you are turning off all the LEDs then turning on some of them again, hence the flashing. As a start try commenting out the for loop that turns the LEDs off. Obviously they will need to be turned off when the minutes go back to zero but not every minute.

#include <Wire.h>           //http://arduino.cc/en/Reference/Wire
#include <Time.h>           //http://playground.arduino.cc/Code/Time
#include <DS3232RTC.h>        //http://github.com/JChristensen/DS3232RTC

byte newMinute = 99; 
const byte LEDs[] = {2, 3, 4, 5};

tmElements_t tm; 

void setup() { 
  Wire.begin();
  Serial.begin(9600);

  setSyncProvider(RTC.get);   // the function to get the time from the RTC
 
   for (byte i=0; i< 4; i++) {
   pinMode (LEDs[i], OUTPUT); 
   
     for (byte i=0; i< 4; i++) {
    pinMode (i + 7, INPUT_PULLUP);
  }
  }
  
}

void loop() {
 
 
   if (digitalRead(6) == LOW) {
    newMinute = 99;
    Serial.println("ButtonPushed");
  PORTD = B00000000;
    }else{
    
    
    
  if (!RTC.read(tm)) { 
  
    time_t t = now();
    int iMinute = minute(t);

    
    if (newMinute != iMinute ) { 
    newMinute = iMinute;  //Set newMinute to the new value
    int y = 2;
    int test;
       
   if ((newMinute % 5) == 0){
          Clear_CornerLEDS(); //minute = 0, 5, 10, ... clear the LEDs
        }else{  
        //Turn on the right LED's for the minutes
          for (int i=1; i <= (newMinute % 5); i++){
            digitalWrite(i+1,HIGH);
          }  
        }
    
  }  
  }
}

Ok this is what I have now, it seems to work :slight_smile:
Is there a solution to work with PORTD? maybe it is only some millis faster, When I am done whit the whole project, are the many millis perhaps 2 seconds…

I see that you still think that you need to use PORTD but I still doubt it.

As to your latest program I have some observations.
You appear to have 4 LEDs as in

const byte LEDs[] = {2, 3, 4, 5};

But in this for loop

      //Turn on the right LED's for the minutes
          for (int i=1; i <= (newMinute % 5); i++){
            digitalWrite(i+1,HIGH);

you do not use the LED array, which would be neater.

In practice, as I pointed out in a previous post, you only need to turn on one extra LED each time the minute increments. In one of your previous posts you had this table

1 minutes = led 1
2 minutes = led 1 & led 2
3 minutes = led 1, led 2 & led 3
4 minutes = led 1, led 2, led 3 and led 4

From it you can see that when the minute changes, and only then, one new LED needs to be turned on, perhaps like this

digitalWrite(LEDS[newMinute - 1], HIGH);

By all means use port manipulation as a learning exercise but is in needed ?

BramWerbrouck:
maybe it is only some millis faster,

It is only a few micros faster.

Write a short test program to repeat digitalWrite() 1000 times and record how long it takes.

…R

UKHeliBob:

digitalWrite(LEDS[newMinute - 1], HIGH);

The problem is: when I power up the clock at - let say 8u03, there should be 3 leds ON but wit the code you wrote, nominate - 1, only the 3th led will be ON… do you understand what I mean?

BramWerbrouck:
The problem is: when I power up the clock at - let say 8u03, there should be 3 leds ON but wit the code you wrote, nominate - 1, only the 3th led will be ON... do you understand what I mean?

Turn on the correct number of LEDs in setup() then let them be updated in loop()

UKHeliBob:
Turn on the correct number of LEDs in setup() then let them be updated in loop()

Would this be faster than what I have??

BramWerbrouck:
Would this be faster than what I have??

Setting the clock LEDs, presumably at least hours and minutes would run as fast as it does at the moment. Updating the minutes LEDs by turning on one LED per minute instead of four in the worst case would of course be faster than now.

Minute 1 - same speed
Minute 2 - twice as fast
Minute 3 - 3 times as fast
Minute 4 - 4 times as fast

In which case when the minutes go from 58 to 59 it will be 59 times as fast to turn on one LED than it would be to turn on 59 LEDs. As for turning them off when the minutes roll over from 59 to zero it would be neat to turn them off from the top down.

How many LEDs are you aiming to have in your clock ?
59 for minutes at least, presumably but you mentioned 100 at one stage

How are you going to drive that many LEDs ?

Perhaps you could share your clock design with us as we are working in the dark at the moment.