First project, problably need help with coding.

UPDATED THE PROBLEM ON PAGE 2.

Hi!
Long story:
I have realized that I'm very interested in electronics for the past year or so. And have now started my first project based on a arduino(I know a little bit late, but have started new job and etc).
I have read quite lot theory on electronics(low level). Aquired tools for electronics(a few multimeters, oscilloscope, DIY variable PSU, good soldering iron etc.). And fooled around with repairs and premade DIY circuits.
But now when I have started my first own project I have realized I'm shitty at programming. And problably have messed up the code so that the circuit does not work. And I need some help with the code.
I dont want just answers that is copy paste solutions. I would love a description of what I did wrong so that I can learn from my mistakes and in the end have competense to code my own projects. Please keep the conversation at a "low level" so my noneducated brain can follow.

TL;DR
I have very little experience in programming. And I think I have totally messed up... PLEASE HELP!

Hardware:
Digispark ATtiny85 clone
rotary encoder with added resistor to enable pushbutton
Green LED(will be replaced by TIP122 transistor and LED strip)

Purpose:
I want to make a LED dimmer. I want to dim a LED strip from ~0-255(analogwrite/PWM) in increments of ~10 for each step on the rotary encoder. The pushbutton on the rotary encoder shall turn on and off the strip.

Schematic:
NIL, will try to make one later, tips on where to make it is welcome.
EDIT:
Made a crude one

Code:

// Firmware for my custom led controller. Used with Digikey ATTiny85.

//Dedicated names for the pins, these will not change.
//CW = CounterWise, CCW = ConterClockWise.
const int ledLevel = 1;
const int cw = 3;
const int ccw = 4;
const int button = 5;

// Set an boolean to save if its ON or OFF. When the code starts the LED will be OFF.
boolean ledOnOff = 0;
// And int's for the rotary encoder
int cwState;
int cwLastState;
int ccwState;
int ccwLastState;
const int changeLedLevel = 12;
int ledIncrese;
int ledDecrease;

void updateLedLevel(int ledIncrese, int ledDecrease)
{
 ledIncrese = ledLevel + changeLedLevel;
 ledDecrease = ledLevel - changeLedLevel;
}


void setup()

//Set all I/O pins
{
 pinMode(ledLevel, OUTPUT);
 pinMode(cw, INPUT);
 pinMode(ccw, INPUT);
 pinMode(button, INPUT);
 ;
}


void loop()
{
 //First check current state of the encoder pins.
 cwState = digitalRead(cw);
 ccwState = digitalRead(ccw);
 //Check if the LED is ON or OFF and switch it with button on encoder.
 digitalRead(button);
 if (button == LOW)
 {
 if (ledOnOff == 0)
 {
 digitalWrite(ledOnOff, 1);
 analogWrite(ledLevel, 126); //If the led is OFF. Switch it with 50% ledLevel on the led
 }
 if (ledOnOff == 1)
 {
 digitalWrite(ledOnOff, 0);; //If the the LED is on. Switch it OFF.
 } 

 }
 if (ledOnOff == 0) // If the LED is switched to off turn off the ledLevel.
 {
 analogWrite(ledLevel, 0);
 }
 if (cwState != cwLastState)
 {
 if (digitalRead(ccw) != cwState);
 {
 analogWrite(ledLevel, ledIncrese);
 }
 
 }
 else
 {
 analogWrite(ledLevel, ledDecrease);
 }
}

Picture of project:

Schematic:
NIL, will try to make one later, t

A schematic is not an optional extra you make after the fact. It is the very first step you have to make. You can not even begin to write code until you have a schematic.

digitalRead(button);

That reads the button pin, but does nothing with the value returned.

if (button == LOW)

The button variable is initialized to 5, so it will never be LOW.

if(digitalRead(button) == LOW)

Makes more sense.

And karma for code tags on your first post.

Grumpy_Mike:
A schematic is not an optional extra you make after the fact. It is the very first step you have to make. You can not even begin to write code until you have a schematic.

Aaaaand it's done! I had one in my mind, but not in print.

expresspcb

digitalRead(button);

-That reads the button pin, but does nothing with the value returned.

Aaah ok. Missed that. In my head it saved the value to be used in next if.

if (button == LOW)

-The button variable is initialized to 5, so it will never be LOW.

Can you explain a little bit more? More specific "initialized to 5".
The thing is that the switch is a NO one and have 5V until I press the button. I thought that was LOW(0V)?
EDIT: Now I think I understood... Because I have set

const int button = 5;

I cant change that value and it cant be anything else. I mix up button and digitalRead(button).

if(digitalRead(button) == LOW)

-Makes more sense.

Will try this. I agree that make sense.

-And karma for code tags on your first post.

Thanks! Thought that if I make it as structered as possible I would get more replies.

When you structure your code well and use good comments you actually help yourself in the long run -

later on you might want to reuse part of today's code and good comments will help you immensely - and yes it will also help people to help you -

you want to make it easy for someone to help you - good code listing (which you have done) - schematic - even if it is hand made - helps people to see what you did -

I had a question about a new to me chip - should have been code compatible with a different chip - and it was after a kind soul found my wire out of place problem, then they added a bit of advice on making the chip function better for the long run (a small cap that I had left out on one of the pins, so was a twofer thing)

Good Luck

Hi,
Magnified view of OP circuit.
t85.jpg
You need a series current limit resistor in the LED lead.
Check if you need pullups on the A and B outputs of the encoder.

I'm not familiar with the Digispark 85, can you get serial comms from it?

Do you have a UNO?

Tom.. :slight_smile:

t85.jpg

beltet:

if (button == LOW)

-The button variable is initialized to 5, so it will never be LOW.

Can you explain a little bit more? More specific "initialized to 5".
The thing is that the switch is a NO one and have 5V until I press the button. I thought that was LOW(0V)?
EDIT: Now I think I understood... Because I have set

const int button = 5;

I cant change that value and it cant be anything else. I mix up button and digitalRead(button).

You might be missing the point a little. 'button' is the pin, not the value / level (1 or 0, HIGH or LOW) on that pin. Even if you omitted the const keyword so it could be changed, it would not work :wink: The value 5 that you assigned to the 'button' variable will never be HIGH (1) or LOW (0). digitalRead(button) indeed solves it.

P5 is the RESET. Can be used as an IO port but makes programming a lot harder, and you can't simply reset the chip any more. Don't do that unless you really have to - in your case, move it to P4.

Serial: there exist SoftwareSerial implementations for the ATtinyx5, including a debugwire iirc it's called that allows for one pin to be a debug output. Only one pin (P0) is still free in this case, that's enough. It can be a great help setting things up.

That circuit is wrong. As mentioned by Tom you need a resistor on the led. Also you need pull down resistors on all three outputs of the encoder, or connect the common of the encoder to ground instead of 5V and enable the internal pull up resistors.

 if (ledOnOff == 0)
 {
 digitalWrite(ledOnOff, 1);
 analogWrite(ledLevel, 126); //If the led is OFF. Switch it with 50% ledLevel on the led
 }
 if (ledOnOff == 1)
 {
 digitalWrite(ledOnOff, 0);; //If the the LED is on. Switch it OFF.
 }
// Set an boolean to save if its ON or OFF. When the code starts the LED will be OFF.
boolean ledOnOff = 0;

ledOnOff is set to boolean, why use digitalWrite(ledOnOff, 1); to set to 1?

it should be

digitalWrite(ledLevel, 1);

same as the digitalWrite(ledOnOff, 0);; ????

That code is a mess.
ledOnOff is not updated when the LED is switched.
Variable names are confusing (why not add Pin to it? Like ledLevelPin - that tells you what it really is - the pin, not the actual brightness level).

Also the layout is a mess - do a ctrl-T in the IDE and it's suddenly a lot more readable.

i see in the code, your inputs are set as INPUT mode...
Change them to INPUT_PULLUP, so you won’t need an external pullup resistor.
(The encoder common will pulse A & B to ground.)

The button is the same, should be INPUT_PULLUP, with the ‘other’ side tied to 0V (not +5)

That will get all your input signals where they should be.

This switch pull-down to 0v when TRUE is called Negative Logic, or Inverted Logic.

Nearly as comprehensive as I said in reply #10.

Hi,

What am working towards is that the OP is a noob, it would be better if the code was developed on a UNO, then ported to the 85.

Programming and simple serial monitoring would be a great help, not just in debugging but learning to code, which I think is the more important at this stage.

Also you diagram shows the 5V supply connected to Vin pin, it should be connected to 5V pin.

Tom... :slight_smile:
(karma added for decent circuit diagram.)

UPDATE:
I realized that I was on the wrong way and needed to start over.
So I found a similiar project on youtube and used most of the code and think I have now understood it(the creator was very thorough with explaining the code).

So here is my new code that works as intended on Arduino Uno(changed board aswell, because my first intended board did not have native interrupt pins):

// Controller code for dimming a LED list. Made for Arduino Uno, But should work on others.

// Used for generating interrupts using CLK signal
const int PinA = 2; 

// Used for reading DT signal
const int PinB = 3;  

// Used for the push button switch
const int PinSW = 4;  

// Simple PWM LED pin
#define PinLED 11

// Keep track of last rotary value
int lastCount = 130;

//Keep track if its on or off, false=Off true=On
int onOff = false;

// Updated by the ISR (Interrupt Service Routine)
volatile int virtualPosition = 130;

// ------------------------------------------------------------------
// INTERRUPT     INTERRUPT     INTERRUPT     INTERRUPT     INTERRUPT 
// ------------------------------------------------------------------
void isr () {
	static unsigned long lastInterruptTime = 0;
	unsigned long interruptTime = millis();

	// If interrupt come faster than 5ms, assume it´s bounce and ignore it
	if (interruptTime - lastInterruptTime > 5){
		if (digitalRead(PinB) == LOW)
		{
			virtualPosition-=5 ; // Decrease virtualPosition with 5
		}
		else {
			virtualPosition+=5 ; // Increase virtualPosition with 5
		}

		// Restrict the value of virtualPosition to be between 5-255, the min and max is "reversed"
		virtualPosition = min(255, max(5, virtualPosition));

		// Keep track of when we were here last (no more than every 5ms)
		lastInterruptTime = interruptTime;
	}
}

// ------------------------------------------------------------------
// SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    SETUP    
// ------------------------------------------------------------------
void setup()
{
	// Just while we debug, view output on serial monitor
	Serial.begin(9600);

	// Rotary pulses are inputs
	pinMode(PinA, INPUT);
	pinMode(PinB, INPUT);

	// Use the built in resistor so we dont need an external on the switch on the encoder
	pinMode(PinSW, INPUT_PULLUP);

	// Attach the routine to service the interrupt
	attachInterrupt(digitalPinToInterrupt(PinA), isr, LOW);

}

// ------------------------------------------------------------------
// MAIN LOOP     MAIN LOOP     MAIN LOOP     MAIN LOOP     MAIN LOOP
// ------------------------------------------------------------------

void loop()
{
	if (digitalRead(PinSW) == LOW) //Reads the rotary encoder switch if pressed
	{
		delay(300); //Some debounce effect.
		if (onOff == false) //If it is off
		{
			analogWrite(PinLED, 130); // Set it at ~half brightness
			virtualPosition = 130; //Set the virtualposition to ~half aswell so it does not go from the latest value when turned off.
			onOff = !onOff; // and switch the state to ON!
			Serial.println("ON!"); // Print it in serial monitor
		}
		else // If its on
		{
			analogWrite(PinLED, 0); //Turn off the LED
			onOff = !onOff; // and switch the state to OFF!
			Serial.println("OFF!"); //Print it in serial monitor
		}	
	}
	if (virtualPosition != lastCount && onOff == true) // its starts to check if the rotary encoder has changed
	{
    	analogWrite(PinLED, virtualPosition); // and updates the brightness.

    	// Write out to serial monitor the value and direction
    	Serial.print(virtualPosition > lastCount ? "Up  :" : "Down:");
    	Serial.println(virtualPosition);
    	if (onOff == false) // If the sate is off 
    	{
    		Serial.println("OFF!"); // Print it in serial monitor
    	}
    	if (onOff == true) // If the state is on
    	{
    		Serial.println("ON!"); //Print it in serial monitor
    	}

		// Keep track of this new value
		lastCount = virtualPosition ;
	}


}

I may need to add more comments. And remove some unnecessary things.

Anyway...

I have another problem... The voltage of the PWM is only at 3.3V(with overshoot) when it´s supposed to be at 5V...
I have checked the voltage with my oscilloscope so that I can rule out a multimeter error due to duty cycle. Se screenshots from oscilloscope:



I also have an overshoot with about 0.5V in the befinning at the pulses. Is that normal? See screenshots:



Anyone knows whats going on? Why I'm a bit worried about the voltage is that I'm going to connect the PWM to a transistor later on that will switch a power supply that provides power to a LED strip. And I'm almost certain the transistor(TIP122) needed 5V on the gate.

Schematic:

Link to youtube video that helped me a LOT!:

And I'm almost certain the transistor(TIP122) needed 5V on the gate.

No you don’t.

You have no current limiting resistor on that LED so you are drawing too much current and so the volatge drops, the LED and the Arduino output get stressed beyond the rated limits and suffers damage. Meaning it will fail sooner than it otherwise would.

Grumpy_Mike:
No you don’t.

You have no current limiting resistor on that LED so you are drawing too much current and so the volatge drops, the LED and the Arduino output get stressed beyond the rated limits and suffers damage. Meaning it will fail sooner than it otherwise would.

I have now added a 180 Ohm resistor between Arduino and LED. And I only get 2.1V output now over the LED. With the overshoot I have 2.4V.
AND I have tested another pin(6) if I have damaged the output on PIN 11. Any other suggestions?
And as I maybe need to draw more than 3A on the TIP122 I would love to have a 5V output instead of 2.1V as the UNO is capable of 5V output.

EDIT:
I have now tested two different arduino boards, and tested different power inputs(bredboard connectors, DC connector) on them without results. The voltage is still on 2.4V including overshoot.
Tips are welcome!

Hi,
What probe are you using on the input to your scope?
If it is in x10 mode, have you compensated it?

Your .5V "glitch", they are not uncommon and can be caused by the probe, will not damage anything if all you are doing is;

  • driving a BJT base via a base resistor.
  • driving a MOSFET gate via a gate resistor.
  • driving an LED via a current limit resistor.

The TIP122 is a Darlington Pair BJT, so its base voltage will be 2 * 0.7 = 1.4V.
You use a base series resisitor to limit the base current, usually dependent on BJT gain and load current.

Can you tell us your electronics, programming, Arduino, hardware experience?

Thanks.. Tom.. :slight_smile: