Atmega8 PD and PC ports - Page 1
Forum section: electronics / beginners

author: Lux_
author_rank: Contributor
timestamp: January 31, 2019, 03:20:34 pm
content: Hello everyone,I follow this forum for a while now but i haven't opened a topic yet, until now.I am a Student studying mechatronica and for a embedded design project i need to design a circuit, so I decided to make something with a atmega8 smd micro controller. I have made multiple projects with arduino's so i am a bit familiar with electronics and code.but i have a problem with a Atmega8 micro controller, let me explain.The micro controller is soldered on a adapter board and then put on a breadboard for testing.I program the micro controller with a Arduino IDE with the Arduino as ISP function.I have made a little program that read 8 thermistors trough a multiplexer(4051) and turn some leds on and off. (the leds don't connect to the multiplexer)I had everything working until i decided to add another led on the PC5 port and coded so that the led turns on and off with a delay of 1 second. But surprisingly another led which is connected to the PD5 port started blinking but the led on port PC5 didn't. When i changed the led on port PC5 to port PC4 and made the change in de code the led didn't blink but another led on PD4 did.I have looked in the Atmega8 datasheet but i am not able to find anything but I am no expert on reading datasheets. So please can someone help me with my problem. Is there a setting or are the ports in someway connected to each other?It is a project for school but i fear i started on something to big with a SMD micro controller.Thanks in advance,Lux_

author: wraper
author_rank: Unknown
timestamp: January 31, 2019, 03:35:23 pm
content: It has nothing to do with MCU/datasheet. It should be something about Arduino library. In any case you can work with port directly, avoiding unnecessary code blob.https://www.arduino.cc/en/Reference/PortManipulation

author: Lux_
author_rank: Contributor
timestamp: January 31, 2019, 03:39:48 pm
content: Thanks for your reaction,I work with the port directly. this is a striped down version of my code which i also uploaded an still the same:Code:void setup() {// put your setup code here, to run once:pinMode(PC4, OUTPUT);}void loop() {// put your main code here, to run repeatedly:digitalWrite(PC4, HIGH);delay(1000);digitalWrite(PC4, LOW);delay(1000);}PD4 still blinks but PC4 doesn't

author: wraper
author_rank: Unknown
timestamp: January 31, 2019, 03:43:44 pm
content: QuoteNope, you don't. You use bloated digitalwrite junk. IO would open library and look if there is any bug in it regarding port C.

author: Lux_
author_rank: Contributor
timestamp: January 31, 2019, 03:49:32 pm
content: QuoteOkay I thought you meant PD5 instead of just 5.But how would you write it? maybe these are newbie questions but i am still learningI am glad that you took the time to read my post.

author: mvs
author_rank: Frequent Contributor
timestamp: January 31, 2019, 03:53:36 pm
content: Quote from: Lux_ on January 31, 2019, 03:39:48 pmYou are using arduino functions pinMode() and digitalWrite(), so its not directly. PC4 is a constant for 4, so you are manipulating arduino pin 4, which is PD4.To manipulate register directly, you need to do something like this:Code:DDRC|=(1<<PC4); // set pin mode to outputPORTC&=~(1<<PC4); // set pin lowPORTC|=(1<<PC4); // set pin high

author: wraper
author_rank: Unknown
timestamp: January 31, 2019, 03:53:55 pm
content: Open the link in my first post and look how to work directly. In any case it's a better way to do this. Half-serious programmer should avoid using digitalwrite function to begin with. It's really unnecessary bloat.

author: Lux_
author_rank: Contributor
timestamp: January 31, 2019, 04:47:06 pm
content: QuoteThanks it works. I think I get it now.Quote from: wraper on January 31, 2019, 03:53:55 pmOkay I didn't know I haven't seen it. You say that your better of with not using digitalwrite ever?First I didn't see the link, but thanks now I can research it.

author: tsman
author_rank: Frequent Contributor
timestamp: January 31, 2019, 05:29:53 pm
content: You're using a constant (PC4) that isn't meant to be used with digitalWrite. digitalWrite is expecting anArduino digital pin or analog input number. If you want to use PC4 which is analog pin 4 in the Arduino numbering scheme for an ATmega8 then you need to use the A4 constant e.g. digitalWrite(A4, HIGH). A4 is actually thenumber 18as that is how they numbered the analog inputs after the digital pins. As mvs noted above, PC4 is actually the number 4 and digitalWrite thinks you're trying to use digital pin 4 which is PD4.

author: Lux_
author_rank: Contributor
timestamp: February 18, 2019, 06:39:31 pm
content: Thanks for all your tips and feedback they helped a lot. I have been trying my best to finish this project but i have another problem with the Atmege8. When i try to turn and of a couple of leds in my main code they emit very dim light, but when I strip all the other code out and only upload just the blink part the glow just as bright as when i couple them to 5v. here is my main code:Code:#include "functions.h"#include <avr/interrupt.h>#include <avr/io.h>void setup() {Serial.begin(300);//Status LED'sDDRD |= (1 << LED_Low);DDRD |= (1 << LED_High);DDRD |= (1 << LED_OK);DDRD |= (1 << LED_DIS);//Mux pinsDDRB |= (1 << MUX_0);DDRB |= (1 << MUX_1);DDRB |= (1 << MUX_2);DDRC |= (0 << ThermistorPin); //Thermistor pinDDRB |= (1 << Buzzer); //Buzzer//BMSPinSelect// interrupt setupGICR |= (1 << INT0); // enable INT0;MCUCR &= ~((1 << ISC01) | (1 << ISC00)); // INT0 low level triggersei(); // enable global interruptDDRD = 0; // all PD pins configured as inputPORTD = (1 << PD2); // enable pull-up on the INT0 pin}void loop() {//Measure all the sensors//Thermistor();//Battery();//SmokeDetector();//Check all the values if they are good.//Check();PORTD|=(1<<LED_Low);delay(1000);PORTD|=(1<<LED_High);delay(1000);PORTD|=(1<<LED_OK);delay(1000);PORTD|=(1<<LED_DIS);delay(1000); // wait for a secondPORTD&=~(1<<LED_Low);delay(1000);PORTD&=~(1<<LED_High);delay(1000);PORTD&=~(1<<LED_OK);delay(1000);PORTD&=~(1<<LED_DIS);delay(1000); // wait for a second}//Interupt loopISR (INT0_vect) {// Serial.println("Interupt detected");Serial.print("*");for (byte dataCount = 0; dataCount <= 7; dataCount++) {Serial.print(0);Serial.print(":"); //Module number and thermistor pin separator symbolSerial.print(dataCount);Serial.print("="); //Thermistor pin and thermistor value separator symbolSerial.print(ThermistorValue);Serial.print(";"); //End of thermistor value}//Error codesSerial.println(WarningStateTemparature); //Print the warningstate of the temparature. 0 = OK, 1 = LOW, 2 = HIGHSerial.println(WarningStateVolage); //Print the warningstate of the voltage. 0 = OK, 1 = LOW, 2 = HIGH, 3 = DischargingSerial.println(WarningStateSmoke); //Print the warningstate of the smoke sensor 0 = OK, 1 = SMOKESerial.print("$"); //End of message separator symbol// prevent interrupt handler from finishing_delay_ms(100); // not good !!!while (!(PIND & (1 << PD2))); // not good !!!_delay_ms(100); // not good !!!}and the funtcions.hCode://LED Pinsconst byte LED_Low = PD4;const byte LED_High = PD5;const byte LED_OK = PD6;const byte LED_DIS = PD7;//Multiplexerconst byte MUX_0 = PB2;const byte MUX_2 = PB0;const byte MUX_1 = PB1;int Mux_Var_0 = 0; //value of select pin at the 4051 (s0)int Mux_Var_1 = 0; //value of select pin at the 4051 (s1)int Mux_Var_2 = 0; //value of select pin at the 4051 (s2)byte MuxCount = 0;//Thermistorfloat ThermistorValue;const byte ThermistorPin = PC2;//add or subtract the value //0 1 2 3 4 5 6 7float ThermistorCalibration = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};//Battery thermistorsbyte ThermistorBatt[] = {0, 1, 2, 3};//Battery temparturebyte TempBattHigh = 40;byte TempBattHighCutoff = 45;byte TempBattLow = 5;byte TempBattLowCutoff = 0;const byte Buzzer = PB6;byte Alarm = 0;//Optocouplerconst byte OPTO_IN = PB7;bool OPTO_IN_State = 0;//Warningstatesbyte WarningStateTemparature = 0;byte WarningStateVolage = 0;byte WarningStateSmoke = 0;//Thermistor calculations:float readingToTemp(float reading) {//Divide by 1023 for the right unitsfloat waarde = 1023 / reading - 1;//Divide by resistor valuewaarde = 10000 / waarde;waarde = waarde / 10000;waarde = log(waarde);waarde /= 3950;waarde += 1.0 / (21 + 273.15);waarde = 1.0 / waarde;waarde = waarde - 273.15;return waarde;}void alarm() {for (byte BuzzerCount = 1; BuzzerCount <= 4; BuzzerCount++) {for (Alarm = 0; Alarm <= 8; Alarm++) {PORTB |= (1 << Buzzer);delay(10);PORTB &= ~(1 << Buzzer);delay(50);}delay(100);}}void Thermistor() {//start multiplexer forloopfor (MuxCount = 0; MuxCount <= 7; MuxCount++) {// select the bitMux_Var_0 = bitRead(MuxCount, 0);Mux_Var_1 = bitRead(MuxCount, 1);Mux_Var_2 = bitRead(MuxCount, 2);digitalWrite(MUX_0, Mux_Var_0);digitalWrite(MUX_1, Mux_Var_1);digitalWrite(MUX_2, Mux_Var_2);//Reset Thermistor valueThermistorValue = 0;//start thermistor forloopfor (byte ThermistorCount = 0; ThermistorCount <= 7; ThermistorCount++) {//Read the analog pin 8 times and add them upThermistorValue = ThermistorValue + analogRead(ThermistorPin);delay(200);}//Divide the themistor value by 8 to get the averageThermistorValue = ThermistorValue / 8;ThermistorValue = readingToTemp(ThermistorValue);ThermistorValue = ThermistorValue + ThermistorCalibration;}}void Battery () {}void SmokeDetector() {}void Check () {//Temperature checkfor (byte Thermistorcheck = 0; Thermistorcheck <= 7; Thermistorcheck++) {//Check if temperature is above temp threshold.if (ThermistorValue >= TempBattHigh) {alarm();WarningStateTemparature = 2;PORTD|=(1<<LED_High);}//Check if temperature is below temp thresholdif (ThermistorValue <= TempBattLow) {alarm();WarningStateTemparature = 1;PORTD|=(1<<LED_Low);}if (ThermistorValue >= TempBattLow && ThermistorValue <= TempBattHigh) {WarningStateTemparature = 0;PORTD|=(1<<LED_OK);}}//Voltage check//Smoke detector check}And here is my striped down code:Code://LED Pinsconst byte LED_Low = PD4;const byte LED_High = PD5;const byte LED_OK = PD6;const byte LED_DIS = PD7;// the setup function runs once when you press reset or power the boardvoid setup() {// initialize digital pin LED_BUILTIN as an output.DDRD |= (1 << LED_Low);DDRD |= (1 << LED_High);DDRD |= (1 << LED_OK);DDRD |= (1 << LED_DIS);}// the loop function runs over and over again forevervoid loop() {PORTD|=(1<<LED_Low);delay(1000);PORTD|=(1<<LED_High);delay(1000);PORTD|=(1<<LED_OK);delay(1000);PORTD|=(1<<LED_DIS);delay(1000); // wait for a secondPORTD&=~(1<<LED_Low);delay(1000);PORTD&=~(1<<LED_High);delay(1000);PORTD&=~(1<<LED_OK);delay(1000);PORTD&=~(1<<LED_DIS);delay(1000); // wait for a second}Its just the same but without the rest of my code which it shouldn't interfere with it.In the main code i even comment out the functions and still it wont work.If you want i can post pictures of the led's but the difference is night and day.I hope some can help just as good as with the previous problem.

author: Nusa
author_rank: Super Contributor
timestamp: February 18, 2019, 09:14:44 pm
content: Quote from: Lux_ on February 18, 2019, 06:39:31 pm300 baud serial? For real?It's not the same unless you also comment out the enabling of thathorriblybehaved interrupt handler, although that isn't your immediate problem:DDRD = 0; // all PD pins configured as inputAll those led output pins are configured as inputs.

author: Lux_
author_rank: Contributor
timestamp: February 19, 2019, 11:13:08 am
content: QuoteYes 300 baud, I sent the serial data trough a optocoupler normal 9600 baud doesn't work its to fast.QuoteSorry It missed that part. But thanks for your feedback on the interupt piece. I have found this piece of code on the internet it said it was a bad practice to do it this way but I don't know what is bad and how to fix it, can you explain? (It works but I want to learn how to do it better.)Quotethis what you get when you're copying code form the internetBut thanks for pointing it out, I just started working with using ports directly.

author: Nusa
author_rank: Super Contributor
timestamp: February 19, 2019, 08:57:22 pm
content: As a rule, interrupt handlers should only do trivial processing if at all possible. And they should exit as soon as possible.For what you're trying to do, I'd suggest that the entire body of the handler should be something like:sendReport = true;add a global initialized to false:bool sendReport = false;Move all your reporting code to its own function:void printReport(){// all that serial data}Then somewhere in your main loop, add:if (sendReport){printReport(); // send the reportsendReport = false; // reset flag set in interrupt}Note that by waiting until the main loop gets to that particular test, you ensure your data is in a valid state for reporting before doing so, and not somewhere in the middle of sensor sampling.

author: Lux_
author_rank: Contributor
timestamp: February 23, 2019, 05:45:54 pm
content: Quote from: Nusa on February 19, 2019, 08:57:22 pmThanks for your time and feedback. While reading your post it help solved another problem which i was having.Most of the time one sensor had "corrupt" data and each time it was another sensor. You're comment help solved this problem, the interrupt interrupted the calculation of the sensor data so that is why i received wrong sensor data.I am glad that people on this forum are so helpful towards beginners. So here is my next question: I finished my schematic and started my PCB layout, but now i am stuck with choosing the right footprint. I am using Kicad 5.0 and i chose for everything a footprint expect my inductor. For my stepup converter i am using a SX1308 with a 10uh inductor.I buy all my components on Aliexpress so I started searching for 10uh inductors I found this:But i don't know which footprint it has and which one I need to choose in Kicad.This is the list of inductor footprints that are available in Kicad:https://github.com/kicad/Inductors_SMD.prettyThanks in advance.Greetings Lux_

author: Nusa
author_rank: Super Contributor
timestamp: February 23, 2019, 06:53:29 pm
content: Go look at some other listings for that part until you find one that's nice enough to include a dimension chart for the part.Then either pick a footprint that seems close enough (solder pads being a bit too big is better than too small -- the most important dimension is adequate separation between the pads) or create a new footprint of your own.