Serial Help

I'm new to programming and cant seem to get this to work. any help would be greatly appreciated. thanks

byte mypins[20] = {PD0,PD1,PD2,PD3,PD4,PD5,PD6,PD7,PB0,PB1,PB2,PB3,PB4,PB5,PC0,PC1,PC2,PC3,PC4,PC5};
void setup(){
  Serial.begin(9600);
  DDRD=0xFF;      
  DDRB=0xFF;      
  DDRC=0xFF;      

}
void loop() {
  for (int i=0; i<=7; ++i){
   PORTD &= ~(1 << mypins[i]-1);  
   PORTD |= 1 << mypins[i]; 
 delay(1000);
  
 if (i > 7 && i <= 13){
   PORTB &= ~(1 << mypins[i]-1);  
   PORTB |= 1 << mypins[i];
   delay(1000);
 }
 else if (i > 13 && i <=20){
   PORTC &= ~(1 << mypins[i]-1);  
   PORTC |= 1 << mypins[i];
   delay(1000);
   }
  }
}

It would be easier to help if you described what it is that you want to do.

Also, if you are new to programming its much easier to use the Arduino abstractions. I think the following is the Arduino version of that code.

void setup(){
  Serial.begin(9600);  // remove this if you are not using the serial port
  for(int i=0; i < 20; i++)  // note that this sets the serial port pins (0 and 1) as outputs!
    pinMode(i,OUTPUT);   
}

void loop() {
  for (int i=0; i<20; i++){
    digitalWrite(i, HIGH);
    delay(1000);
    digitalWrite(i,LOW);
  }    
}

cant seem to get this to work

In what way does it not work?

@mem: i know i could use digitalWrite to just light an LED but im trying to use the PWMAllPins code in the playground to get PWM-like results from every pin and it seems i cant use digitalWrite, i have to mess with the registers.

@Anachocomputer: It wont work in that it wont light any LEDs. I can get them to light up if i just do

PORTB |= 1 << PB0;

but when i try my code nothing lights up. not sure if i made my array correctly or if my math isnt right or something.
what im trying to accomplish is turn off and on ports 0-19 one by one for now then hopefully try to finagle the PWMAllPins code to light em up at 50% power etc.

I haven't dissected all of this, but if your for loop moves i from 0 to 7, the clauses if (i>7...) and if (i>13...) will never trigger.

Also, if these clauses were meant to be complementary, they aren't. Why the "-1"?

PORTD &= ~(1 << mypins*-1);*
_ PORTD |= 1 << mypins*;*_
*Lastly, if you perform those two operations successively, they happen so fast you'll never notice. *
Maybe I did dissect it all? :slight_smile:
Mikal

Mikal, just the guy i was hoping would comment! you helped me out before and i was trying to take what i learned from that and use it on this. i was hoping PORTD &= ~(1 << mypins*-1); would shut off the previously lit LED before turning on the next one.*
as far as my i=0; i<7;++i goes, well..guess its a good old fashioned flub haha. can i do andif right after the for? have it count to 20 and have 3 different conditions to watch for?
* *for (int i=0; i<20; ++i){ if (i <= 7){ do this if (i > 7 && i <= 13){ do this if (i > 13){ do this   }  } } }* *
or am i completely wrong? haha

Almost right. You want

for (int i=0; i<20; ++i){
if (i <= 7){
 do this
}
else if (i > 7 && i <= 13){
 do this
}
else if (i > 13){
 do this
}

I assume that

PORT |= 1 << mypins[i];

brings a pin high? (Too lazy to look it up. :)). If so, to turn it off you want

PORT &= ~(1 << mypins[i]);

No -1.

Mikal

yes, youre correct
PORT |= 1 << mypins*; turns the pin high and*
PORT &= ~(1 << mypins*); turns it off.*
thanks. ill give this a shot

awesome job Mikal, thanks again. it works! although at first it was keeping LEDs on and blinking them off, just had to reverse the order of

PORT |= 1 << mypins*;*
PORT &= ~(1 << mypins*);*
and now they stay off and blink on! thanks a bunch.
Now to try to figure out how to get them to fade...

PORTD &= ~(1 << mypins[i]-1);
  PORTD |= 1 << mypins[i];

Huh. I had assumed that the "-1" was to turn off the "previous" LED to get a chase sort of effect, but if so it is in the wrong place. Should be:

PORTD &= ~(1 << mypins[i-1]);
  PORTD |= 1 << mypins[i];

(and it will need some special handling for i==0 !)

I wonder if Trav603 will find it easer to work with a simpler syntax. The following uses macros to do direct port IO but maintains an arduino style syntax. The code should cycle through each LED, turning off the previous one.

#define FIRST_PIN  0
#define LAST_PIN   19

#define fastWriteHigh(_pin_) ( _pin_ < 8 ?  PORTD |= 1 << (_pin_ & 0x07) : ( _pin_ < 14 ?  PORTB |= 1 << ((_pin_ -8) & 0x07) : PORTC |= 1 << ((_pin_ -14) & 0x07)  ) ) 
#define fastWriteLow(_pin_) ( _pin_ < 8 ?   PORTD &= ~(1 << (_pin_  & 0x07)) : ( _pin_ < 14 ?  PORTB &= ~(1 << ((_pin_ -8) & 0x07) )  :  PORTC &= ~(1 << ((_pin_ -14) & 0x07) )  ) )

void setup(){
  Serial.begin(9600);  // remove this if you are not using the serial port
  for(int i=FIRST_PIN; i <= LAST_PIN; i++)  // note that this sets the serial port pins (0 and 1) as outputs!
    pinMode(i,OUTPUT);  
}

void loop() {
  for (int i = FIRST_PIN; i <= LAST_PIN; i++){
    fastWriteHigh(i);
    if(i > FIRST_PIN)
       fastWriteLow(i-1);
    else
       fastWriteLow(LAST_PIN);
    delay(1000);  
  }    
}

A very good improvement indeed. And I would think that you could abandon having to calculate the "previous" pin by simply unwinding the loop a bit like this:

void loop() {
  for (int i = FIRST_PIN; i <= LAST_PIN; i++){
    fastWriteHigh(i);
    delay(1000);
    fastWriteLow(i);
  }
}

M

Can I ask why you elected to use a macro instead of a function with the inline modifier?

... I would think that you could abandon having to calculate the "previous" pin by simply unwinding the loop a bit ...

The OP wants to enhance the code to do PWM, I simply implemented the logic in the first post using the simpler syntax.

Can I ask why you elected to use a macro instead of a function with the inline modifier?

when I wrote those, the inline version produced less efficient code than the macro version. I Haven't tried it with the compiler used in verison 0012. mind you, my application used consants as pins so the compiler produced a single machine instruction to do the output. With a variable as the argument the resulting code may not be more efficient.

@mem: i think i follow your code :slight_smile: im always game to learn something :slight_smile:

the only thing is..i wanted to figure out how to turn pins off and on in serial just as a step(i guess you could say) towards the final project. im still trying to figure out how to 'emulate' PWM on these pins.

what im aiming for is:

LED1 100% then LED2 100%, LED1 66% then LED3 100%, LED2 66%, LED1 33% then LED4 100%, LED3 66%, LED2 33%, LED1 OFF.

sorry if my example is jumbled but i think you could picture what im trying to accomplish hah. like a bright LED traveling in a circle and leaving a fading trail. i figured if i could get the blinking off and on to work first, maybe i could try to plugin what i need to vary the brightness of the LEDs

i took the PWMAllPins code from playground. if i change all the values in the sinewave array to to 0x20(32 in dec) the LED stays lit at about 1/4 power. Would anyone know another way to accomplish this without an array?

Something like this might get you started, Trav. You sometimes see games in arcades with a bunch of LEDs arranged in a circle. They illuminate consecutively in the way you describe, and if you press the button precisely as the main LED lights up, you win the "big prize". I've often thought it would be fun to build a toy like that with Arduino, although you'd have to solve the problem of having more LEDs than pins.

Mikal

#define NUMLEDS 15

// TAILLENGTH is the number of LEDs in the tail of the "comet"
#define TAILLENGTH 3

// DELTA is the number of milliseconds you wait before moving to the next LED
#define DELTA 500

// pins is the mapping from LED # to Arduino pin #
byte pins[NUMLEDS] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};

// duty_cycle is an array tracking the current state of each LED between 0 (off) and 10 (full bright)
byte duty_cycle[NUMLEDS];

// head_led shows which LED is currently the head
byte head_led = TAILLENGTH;

// track the last time we moved to a new head LED
unsigned long last_shift_time = 0xF0000000;

void setup() 
{
  for (int i=0; i<NUMLEDS; ++i)
    pinMode(pins[i], OUTPUT);
}

void loop()
{
  unsigned long m = millis();
  
  // Is it time to shift?
  if (m - last_shift_time > DELTA)
  {
    last_shift_time = m;
    shift();
  }
  
  // Display LEDs in their current state
  display();
}

void shift()
{
  // Choose a new head LED -- the neighbor to the right
  head_led = (head_led + 1) % NUMLEDS;

  // Clear out the duty_cycle array
  memset(duty_cycle, 0, sizeof(duty_cycle));

  // Of course the head LED will be 10/10 bright
  duty_cycle[head_led] = 10;

  // The "tail" LEDs will be linearly dimmer
  for (int i=0; i<TAILLENGTH; ++i)
  {
    int led = (head_led + NUMLEDS - i - 1) % NUMLEDS;
    duty_cycle[led] = 10 - 10 * (i+1) / (TAILLENGTH + 1);
  }
}

void display()
{
  // time is a number between 0 and 9
  unsigned long time = millis() % 10;

  // simulate PWM by turning LEDs on/off based on "time"
  // and their value in the duty_cycle array.  If the
  // duty_cycle is 10, it's always on.  0, never on.
  // 5 -- on 50% of the time, etc.  For every 10ms that
  // elapse, the LED is on duty_cycle[i] ms.
  for (int i=0; i<NUMLEDS; ++i)
  {
    if (duty_cycle[i] > time)
      digitalWrite(pins[i], HIGH);
    else
      digitalWrite(pins[i], LOW);
  }
}

EDIT: posted this before i saw Mikals post. thanks. ill have to give that a try!

so messing around with PWMAllPins i got this:

float pwmSpeed[17] = {
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};             // these constants set the rate of dimming
int pwmVal[14];                                                               // PWM values for 12 channels - 0 & 1 included but not used
float pwmFloats[14];
int i, j, k, l, x, y, z, bufsize, pot;                                        // variables for various counters

unsigned char sinewave[] =        //256 values
{
  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,

  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,

  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,

  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,

  0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,

  0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,

  0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,

  0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,

  0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,

  0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,

  0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

  0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

  0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

  0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

  0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

  0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20

};


void setup(){
  Serial.begin(9600);
  DDRD=0xFC;      // direction variable for port D - make em all outputs except serial pins 0 & 1
  DDRB=0xFF;      // direction variable for port B - all outputs 

}

void loop(){

  // time = millis();               // this was to test the loop speed 
  // for (z=0; z<1000; z++){        // ditto

  //  pot = analogRead(0);          // this implemented a potentiometer speed control to control speed of fading

  for (y=0; y<14; y++){             // calculate one new pwm value every time through the control loop
    j = (j + 1) % 12;              // calculate a new j every time - modulo operator makes it cycle back to 0 after 11
    k = j + 2;                      // add 2 tp tje result - this yields a cycle of 2 to 13 for the channel (pin) select numbers

    pwmFloats[k] =  (pwmFloats[k] + pwmSpeed[k]);
    // pwmFloats[k] =  (pwmFloats[k] + ((pwmSpeed[k]  * 15 * (float)pot) / 1023));    // implements potentiometer speed control - see line above

      if (pwmFloats[k] >= 256){                  // wrop around sinewave table index values that are larger than 256
      pwmFloats[k] = pwmFloats[k] - 256;
    }
    else if  (pwmFloats[k] < 0){
      pwmFloats[k] = pwmFloats[k] + 256;        // wrop around sinewave table index values that are less than 0
    }

    pwmVal[k] = sinewave[(int)pwmFloats[k]];                   // convert the float value to an integer and get the value out of the sinewave index
  }

  PORTD = 0xFC;              // all outputs except serial pins 0 & 1
  PORTB = 0xFF;              // turn on all pins of ports D & B

for (z=0; z<3; z++){         // this loop just adds some more repetitions of the loop below to cut down on the time overhead of loop above
                             // increase this until you start to preceive flicker - then back off - decrease for more responsive sensor input reads
  for (x=0; x<256; x++){
    for( i=2; i<14; i++){    // start with 2 to avoid serial pins
      if (x == pwmVal[i]){
        if (i < 8){    // corresponds to PORTD
          // bitshift a one into the proper bit then reverse the whole byte
          // equivalent to the line below but around 4 times faster
          // digitalWrite(i, LOW);
          PORTD = PORTD & (~(1 << i));
        }   
        else{   
          PORTB = PORTB & (~(1 << (i-8)));         // corresponds to PORTB - same as digitalWrite(pin, LOW); - on Port B pins
        }

      }
    }
  }
}
  //    }
  //    Serial.println((millis() - time), DEC);     // speed test code

}

which blinks an LED through 3 different brightness levels.
i dont totally understand the

float pwmSpeed[17] = {
 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};

seems like if i set it anything besides 0 they blink the same. it was originally pwmSpeed[14] but it seems the more values in the array the longer it takes to go through the different levels of brightness. when i try to add output to PORTC things get screwy. if you mess around with this and get it to work on all pins in all ports let me know please :slight_smile: and if you figure out how to get to animate like i said previously in the post you will be my hero

Thanks Mikal, your code worked out awesome. Looks easier than doing all that serial stuff. this is great stuff for anyone else who was looking for 'more PWM pins' :slight_smile:

im not sure if you hooked up any LEDs and tried this but cranking up the DELTA to
#define DELTA 53
makes for a pretty awesome effect!

im not sure if you hooked up any LEDs and tried this but cranking up the DELTA...

No, I'm afraid I only tested this in the Arduino in my brain, but I'm glad to hear it works. Post a video? :slight_smile: I'd like someday to extend the concept to, say, 256 LEDs. Power won't be a problem as long as I keep TAILLENGTH somewhat low, but I'll have to get out some shift registers or something. Thanks.

Mikal