Author Topic: Atmega8 PD and PC ports  (Read 2476 times)

0 Members and 1 Guest are viewing this topic.

Offline Lux_Topic starter

  • Contributor
  • Posts: 11
  • Country: nl
Atmega8 PD and PC ports
« on: January 31, 2019, 03:20:34 pm »
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_
 

Online wraper

  • Supporter
  • ****
  • Posts: 17952
  • Country: lv
Re: Atmega8 PD and PC ports
« Reply #1 on: January 31, 2019, 03:35:23 pm »
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
« Last Edit: January 31, 2019, 03:37:10 pm by wraper »
 

Offline Lux_Topic starter

  • Contributor
  • Posts: 11
  • Country: nl
Re: Atmega8 PD and PC ports
« Reply #2 on: January 31, 2019, 03:39:48 pm »
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: [Select]
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
 

Online wraper

  • Supporter
  • ****
  • Posts: 17952
  • Country: lv
Re: Atmega8 PD and PC ports
« Reply #3 on: January 31, 2019, 03:43:44 pm »
Quote
I work with the port directly.
Nope, you don't. You use bloated digitalwrite junk. IO would open library and look if there is any bug in it regarding port C.
« Last Edit: January 31, 2019, 03:46:14 pm by wraper »
 

Offline Lux_Topic starter

  • Contributor
  • Posts: 11
  • Country: nl
Re: Atmega8 PD and PC ports
« Reply #4 on: January 31, 2019, 03:49:32 pm »
Quote
Nope, you don't. You use bloated digitalwrite junk. IO would open library and look id there is any bug in it regarding port C.
Okay I thought you meant PD5 instead of just 5.
But how would you write it? maybe these are newbie questions but i am still learning :) I am glad that you took the time to read my post.
 

Offline mvs

  • Frequent Contributor
  • **
  • Posts: 370
  • Country: de
Re: Atmega8 PD and PC ports
« Reply #5 on: January 31, 2019, 03:53:36 pm »
I work with the port directly. this is a striped down version of my code which i also uploaded an still the same:
Code: [Select]
pinMode(PC4, OUTPUT);
...
digitalWrite(PC4, HIGH);
...
digitalWrite(PC4, LOW);

You 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: [Select]
 
DDRC|=(1<<PC4); // set pin mode to output
PORTC&=~(1<<PC4); // set pin low
PORTC|=(1<<PC4); // set pin high
 

Online wraper

  • Supporter
  • ****
  • Posts: 17952
  • Country: lv
Re: Atmega8 PD and PC ports
« Reply #6 on: January 31, 2019, 03:53:55 pm »
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.
 

Offline Lux_Topic starter

  • Contributor
  • Posts: 11
  • Country: nl
Re: Atmega8 PD and PC ports
« Reply #7 on: January 31, 2019, 04:47:06 pm »
Quote
You 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: [Select]
 
DDRC|=(1<<PC4); // set pin mode to output
PORTC&=~(1<<PC4); // set pin low
PORTC|=(1<<PC4); // set pin high

Thanks it works. I think I get it now.

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.

Okay 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.
 

Offline tsman

  • Frequent Contributor
  • **
  • Posts: 599
  • Country: gb
Re: Atmega8 PD and PC ports
« Reply #8 on: January 31, 2019, 05:29:53 pm »
You're using a constant (PC4) that isn't meant to be used with digitalWrite. digitalWrite is expecting an Arduino 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 the number 18 as 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.
« Last Edit: January 31, 2019, 05:33:53 pm by tsman »
 

Offline Lux_Topic starter

  • Contributor
  • Posts: 11
  • Country: nl
Re: Atmega8 PD and PC ports
« Reply #9 on: February 18, 2019, 06:39:31 pm »
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: [Select]
#include "functions.h"
#include <avr/interrupt.h>
#include <avr/io.h>



void setup() {
  Serial.begin(300);
  //Status LED's
  DDRD |= (1 << LED_Low);
  DDRD |= (1 << LED_High);
  DDRD |= (1 << LED_OK);
  DDRD |= (1 << LED_DIS);

  //Mux pins
  DDRB |= (1 << MUX_0);
  DDRB |= (1 << MUX_1);
  DDRB |= (1 << MUX_2);
 
  DDRC |= (0 << ThermistorPin);     //Thermistor pin
  DDRB |= (1 << Buzzer);            //Buzzer

  //BMSPinSelect
  // interrupt setup
  GICR  |= (1 << INT0);                // enable INT0;
  MCUCR &= ~((1 << ISC01) | (1 << ISC00)); // INT0 low level trigger
  sei();              // enable global interrupt
  DDRD  = 0;          // all PD pins configured as input
  PORTD = (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 second
  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 second

}


//Interupt loop
ISR (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 symbol
    Serial.print(dataCount);
    Serial.print("=");  //Thermistor pin and thermistor value separator symbol
    Serial.print(ThermistorValue[dataCount]);
    Serial.print(";");  //End of thermistor value
  }
  //Error codes
  Serial.println(WarningStateTemparature);  //Print the warningstate of the temparature. 0 = OK,  1 = LOW, 2 = HIGH
  Serial.println(WarningStateVolage);       //Print the warningstate of the voltage. 0 = OK, 1 = LOW, 2 = HIGH, 3 = Discharging
  Serial.println(WarningStateSmoke);        //Print the warningstate of the smoke sensor 0 = OK, 1 = SMOKE

  Serial.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.h
Code: [Select]
//LED Pins
const byte LED_Low = PD4;
const byte LED_High = PD5;
const byte LED_OK = PD6;
const byte LED_DIS = PD7;
//Multiplexer
const 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;
//Thermistor
float ThermistorValue[8];
const byte ThermistorPin = PC2;
//add or subtract the value     //0    1    2    3    4    5    6    7
float ThermistorCalibration[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
//Battery thermistors
byte ThermistorBatt[] = {0, 1, 2, 3};
//Battery temparture
byte TempBattHigh = 40;
byte TempBattHighCutoff = 45;
byte TempBattLow = 5;
byte TempBattLowCutoff = 0;
const byte Buzzer =  PB6;
byte Alarm = 0;
//Optocoupler
const byte OPTO_IN = PB7;
bool OPTO_IN_State = 0;
//Warningstates
byte WarningStateTemparature = 0;
byte WarningStateVolage = 0;
byte WarningStateSmoke = 0;


//Thermistor calculations:
float readingToTemp(float reading) {
  //Divide by 1023 for the right units
  float waarde = 1023 / reading - 1;
  //Divide by resistor value
  waarde = 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 forloop
  for (MuxCount = 0; MuxCount <= 7; MuxCount++) {
    // select the bit
    Mux_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 value
    ThermistorValue[MuxCount] = 0;
    //start thermistor forloop
    for (byte ThermistorCount = 0; ThermistorCount <= 7; ThermistorCount++) {
      //Read the analog pin 8 times and add them up
      ThermistorValue[MuxCount] = ThermistorValue[MuxCount] + analogRead(ThermistorPin);
      delay(200);
    }
    //Divide the themistor value by 8 to get the average
    ThermistorValue[MuxCount] = ThermistorValue[MuxCount] / 8;
    ThermistorValue[MuxCount] = readingToTemp(ThermistorValue[MuxCount]);
    ThermistorValue[MuxCount] = ThermistorValue[MuxCount] + ThermistorCalibration[MuxCount];
  }
}

void Battery () {
}

void SmokeDetector() {

}

void Check () {

  //Temperature check
  for (byte Thermistorcheck = 0; Thermistorcheck <= 7; Thermistorcheck++) {
    //Check if temperature is above temp threshold.
    if (ThermistorValue[Thermistorcheck] >= TempBattHigh) {
      alarm();
      WarningStateTemparature = 2;
      PORTD|=(1<<LED_High);
    }
    //Check if temperature is below temp threshold
    if (ThermistorValue[Thermistorcheck] <= TempBattLow) {
      alarm();
      WarningStateTemparature = 1;
      PORTD|=(1<<LED_Low);
    }
    if (ThermistorValue[Thermistorcheck] >= TempBattLow && ThermistorValue[Thermistorcheck] <= TempBattHigh) {
      WarningStateTemparature = 0;
      PORTD|=(1<<LED_OK);
    }
  }

  //Voltage check
 
 
 
  //Smoke detector check


}


And here is my striped down code:

Code: [Select]
//LED Pins
const 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 board
void 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 forever
void 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 second
  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 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.
 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2418
  • Country: us
Re: Atmega8 PD and PC ports
« Reply #10 on: February 18, 2019, 09:14:44 pm »
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.
300 baud serial? For real?

It's not the same unless you also comment out the enabling of that horribly behaved interrupt handler, although that isn't your immediate problem:

DDRD  = 0;          // all PD pins configured as input
All those led output pins are configured as inputs.
 
The following users thanked this post: Lux_

Offline Lux_Topic starter

  • Contributor
  • Posts: 11
  • Country: nl
Re: Atmega8 PD and PC ports
« Reply #11 on: February 19, 2019, 11:13:08 am »
Quote
300 baud serial? For real?
Yes 300 baud, I sent the serial data trough a optocoupler normal 9600 baud doesn't work its to fast.

Quote
It's not the same unless you also comment out the enabling of that horribly behaved interrupt handler, although that isn't your immediate problem:
Sorry 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.)

Quote
DDRD  = 0;          // all PD pins configured as input
All those led output pins are configured as inputs.

 :palm: this what you get when you're copying code form the internet :) But thanks for pointing it out, I just started working with using ports directly.
 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2418
  • Country: us
Re: Atmega8 PD and PC ports
« Reply #12 on: February 19, 2019, 08:57:22 pm »
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 report
      sendReport = 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.
 
The following users thanked this post: Lux_

Offline Lux_Topic starter

  • Contributor
  • Posts: 11
  • Country: nl
Re: Atmega8 PD and PC ports
« Reply #13 on: February 23, 2019, 05:45:54 pm »
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 report
      sendReport = 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.

Thanks 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.pretty

Thanks in advance.

Greetings Lux_




 

Offline Nusa

  • Super Contributor
  • ***
  • Posts: 2418
  • Country: us
Re: Atmega8 PD and PC ports
« Reply #14 on: February 23, 2019, 06:53:29 pm »
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.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf