port read

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi I am looking to read out the value of a complete 8bit port ( A on mega pins 22-29 ) and convert that info to an int value ( 1-256 ) for use as an address.

 

Unit8_t VAR = PinA  ??

 

-Peter

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
Unit8_t VAR = PinA

 

 

Maybe try:

uint8_t VAR = PINA;

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for that.

 

how might I go about converting that to it's int value? 1-512

I'm looking to use dip switches to set a start address which is used as an offset for the number of addresses each receiver has ( this is an RS 485 (DMX) project ) 

each receiver can set its own start address.

 

Thanks again

 

-Peter

 

Last Edited: Sat. Apr 25, 2020 - 02:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well first off, an 8 bit unsigned integer has 256 possible values >>0 - 255<<.  Not 1 - 256, which would require a 16 bit address.

 

Upstage wrote:
how might I go about converting that to it's int value without reading it out and adding it up?

I do not follow the question.

 

If you 'READ' the value on PortA via PINA, into variable 'VAR' its already done for you.

 

For example, if ALL teh pins on PortA are logic '0' then the value of 'VAR' would be 0x00hex (0 in decimal) when the line of code above is performed. 

 

Likewise if only Bit7 of PortA is logic '1', then the value of 'VAR' would be 0x80hex (128 in decimal) when the line of code is performed.

 

What other 'conversion' are you referring to?

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You edited while I was typing.......

 

I thought DMX used a 16bit address....

 

Then your DIP switches will be on TWO ports, not just one.

 

REad each port into its own VARiable  Let's say AddrLOW, and AddrHigh- Both 8 bit.

 

You then can do a simple OR with a mask to a 16bit variable for the full address: DMXAddress for example.

 

Another approach is to not bother doing ANYTHING with the High and Low address variables as the AVR USART can only send 8 bit chunks anyway....which the DMX receiver can handle as you will be sending oout your data in a DMX formatted PROTOCOL.

 

do a search of the forums here, and a direct Google Search of DMX and AVR.  This has come up many times in the past.

 

JIm

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi yes 9 bits anyway?  1-512  hence DMX512 as the standard. ( the offset is done in math 0-511 + 1? )

 

the addressing I'm looking to do is on the receiver side. dip switches set the offset start address for each fixture in a chain. so it only receives relevant data. currently the fixtures I'm developing are 12ch each 8bit per channel (0-255)

 

I am currently just using an int offset in the code to test addressing and it works, so I am looking to replace that static offset value with the address from the dip switches.

 

-Peter

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgmdesign wrote:

I thought DMX used a 16bit address....

 

It's actually a 9-bit address.

 

jgmdesign wrote:

Then your DIP switches will be on TWO ports, not just one.

 

But this still holds true. You have 8 bits on one port and the 9th bit on another. Two reads of the ports, a mask, a shift and an add into the int16_t result.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

So. how is your 9-bit DIP switch wired up? What ports and what pins?

 

At least one other on here is working on DMX at the moment....

 

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Last Edited: Sat. Apr 25, 2020 - 03:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've got all of port A 0-7 full I haven't added the 9th bit yet though I could use the low bit on port B or C and use it for the 9th? (256) 

 

 

You have 8 bits on one port and the 9th bit on another. Two reads of the ports, a mask, a shift and an add into the int16_t result.

 

So read both as unit8_t ? or read them in as unit16_t to begin with?

convert the 2nd one to unit16_t and shift the data

then add them?

 

haven't done this before any help or guidance is appreciated.

 

-Peter

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Untested...

 

#include <mega328p.h>
#include <stdint.h>

uint16_t	dmx_addr;

void main(void) {

	//assumes bits 0 - 7 are on PC0 - PC7
	//assumes bit 8 is on PB4
	dmx_addr = ((uint16_t)(PINB & 0b00010000) << 4) + PINC;
}

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
assumes bits 0 - 7 are on PC0 - PC7

 

might be slightly more visually pleasing, since an 8th bit is thereafter being added on the "left" (and not on the "right"):

assumes bits 7 - 0 are on PC7 - PC0

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks guys,

 

I'm using a mega2560 so adapting to it I was thinking

 

#include <stdint.h>
pinMode(22, INPUT_PULLUP); //Port A
pinMode(23, INPUT_PULLUP);
pinMode(24, INPUT_PULLUP);
pinMode(25, INPUT_PULLUP);
pinMode(26, INPUT_PULLUP);
pinMode(27, INPUT_PULLUP);
pinMode(28, INPUT_PULLUP);
pinMode(29, INPUT_PULLUP);

pinMode(37, INPUT_PULLUP); //Port C0

uint16_t	dmx_addr;

void main(void) {

	//assumes bits 0 - 7 are on PA0 -PA7
	//assumes bit 8 is on PC0
	dmx_addr = ((uint16_t)(PINC & 0b00010000) << 4) + PINA;
}

 

I'm not at the project right now, hoping to weed out some issues before I get back to it.

 

-Peter

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You'll need to tweak this...

 

PINC & 0b00010000) << 4

...to suit your actual pins used.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PinMode() (in Arduino at least) is a callable function. You can't put an invocation outside of the body of a function. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello good from the beginning forgive my bad english
what you are looking to do is this

// ************* get DMX start address **************
void get_dips (void)
{
#ifdef USE_DIP
uint16_t Temp;
 
if (! (PINE & (1 << PE1))) {// pin10 enable or disable DMX reception
Temp =
(! (PINC & (1 << PC0)) * 1) +
(! (PINC & (1 << PC1)) * 2) +
(! (PINC & (1 << PC2)) * 4) +
(! (PINC & (1 << PC3)) * 8) +
(! (PINC & (1 << PC4)) * 16) +
(! (PINC & (1 << PC5)) * 32) +
(! (PINC & (1 << PC6)) * 64) +
(! (PINC & (1 << PC7)) * 128) +
(! (PINE & (1 << PE2)) * 256);
 
 
if (Temp! = 0)
{
DmxAddress = Temp;

}
else
{
UCSR0B & = ~ (1 << RXCIE0); // disable Receiver if start address = 0
for (Temp = 0; Temp <sizeof (DmxRxField); Temp ++)
{
DmxRxField [Temp] = 0;
}
}
#endif

they will ask why the full port is not read
good to set the correct address in DMX are 9 values ​​that add up
If you pay attention to the example you will see that the nine keys placed in GND
gives a value of 512 which is the maximum allowed by the DMX protocol per universe
pin 10 of the keys for the master or slave function
now if you want to save pins you can use the module tm1637 in arduino plus the addition of buttons
https://www.instructables.com/id...

/ *

   This software is based on the TM1637 library.
   This software is free to use as long as it is not used for commercial purposes, if you like to use this commercially, please send me an email.
   This software is writen by joram de Poel: joramdepoel@gmail.com, mail me if you have any questions.

   A library will be released in the future to make using the interface even easier.

   latest update: 7-12-2018

* /

#define softwareVersion 0.6

// display setup
#include <TM1637.h> // interface module with display, buttons and status leds
#include <EEPROM.h> // store the DMX adress in EEPROM

#define manual 0 // define mode
#define DMX 1

unsigned int displayUpdateDelay = 200; // update display every 200ms
unsigned long lastDisplayUpdate; // to keep track of refresh rate
byte leds = 0x00; // binairy for 8 leds: b00000111, 0x07 all on

// DMX setup
int DMX_addr = 1; // start adress for DMX
unsigned int DMX_ch_used = 6; // this prevents you from setting an adres which is out of range. (setting 511 as start adres will make the last adres 517 which does not exist)
bool DMX_addr_has_changed = false; // DMX addr is changed -> store it to EEPROM
unsigned int DMX_addr_store_delay = 2000; // ms to wait before storing the addr
unsigned long last_addr_change = 0; // when was the last DMX addres change?
bool mode = DMX;

// pin definitions
#define CLK 2 // pins definitions for TM1637 and can be changed to other ports
#define DIO 3

TM1637 module (DIO, CLK); // define the module

void setup () {
  delay (500); // wait for capacitors to charge and external driver to start

  module.clearDisplay (); // clear the display, this is needed when the Arduino is reset without disconnecting the power from the interface module.
  delay (1);
  module.setupDisplay (true, 7);
  delay (1);
  module.setDisplayToString ("boot"); // show the text booting

  // do the rest of the setup here

  // this is the last part of the setup
  readDMXAddr (); // get DMX addr from EEPROM and put it on the screen

}

void loop () {

  unsigned long lastPacket = 200; // you should update this every time a new DMX package is received
 
  // change the status led for DMX according to the time since the last packet
  (lastPacket> 500)? leds & = 0x03: leds | = 0x04; // bitmasks are used to select which leds are on or off depending on the time since the last DMX package. this only affects the DMX status led.
 
  if (DMX_addr_has_changed) {
    if (millis ()> last_addr_change + DMX_addr_store_delay) {
      saveDMXAddr (); // save the DMX addr to EEPROM after 2 seconds and show SAVE
    }
  }

  if (millis () - lastDisplayUpdate> displayUpdateDelay) {// only update the display at a fixed rate to reduce CPU load.
    updateDisplay (); // update display
    readButtons (); // check if any buttons are pressed
    lastDisplayUpdate = millis (); // update counter to current time
  }

  // put your code below this line, when using delays the button read might not always responds and the display will not update!

}

void updateDisplay () {
  char screenData [4]; // 4 digits
  sprintf (screenData, "A% 03u", DMX_addr); // print like A027, if you prefer the adres as d027 you can change the "A% 03u" to "d% 03u"
  module.setDisplayToString (screenData); // convert the data to text
  module.setSegments (leds, 4); // turn on or off the status leds. You can connect 8 leds if you like and this code does support it.
}

void readButtons () {
  byte btButtons = module.getButtons (); // you can read out 16 buttons with this code, this code does not allow multi button presses

  if (btButtons) // if a button is touched
  {
    if (btButtons == 0x08) {//// b00001000 first button = menu
      ; // do something when this button is pressed
    }
    if (btButtons == 0x04) {// b00000100 second button = up
      DMX_addr + = 1; // increase the DMX addres by one
      if (DMX_addr> (512 - DMX_ch_used)) {// only do this when possible, if over the highest one go to 1
        DMX_addr = 1;
      }
      last_addr_change = millis (); // update timer for addr change
      DMX_addr_has_changed = true; // set a flag to save the addr
    }
    if (btButtons == 0x02) {// b00000010 third button = down
      DMX_addr - = 1; // same as up but this time down
      if (DMX_addr <1) {// go to the highest possible addr when going below 1
        DMX_addr = 512 - DMX_ch_used;
      }
      last_addr_change = millis (); // update timer for addr change
      DMX_addr_has_changed = true; // and set a flag
    }
    if (btButtons == 0x01) {// b00000001 fourth button = enter
      ; // do something you like
    }
  }
}

// function to store the DMX addres to EEPROM and keep it when the device is turned off
void saveDMXAddr () {
  EEPROM.write (0, highByte (DMX_addr)); // 255 is the highest value you can store in one EEPROM addres so we split it
  EEPROM.write (1, lowByte (DMX_addr)); // this is the other part
  DMX_addr_has_changed = false; // reset flag because the addr is saved
  module.setDisplayToString ("SAvE"); // display SAvE on the display, SAVE is not displayed correctly so a lowercase 'V' is used
  delay (500);
}

// restore the DMX addres from the EEPROM
void readDMXAddr () {
  byte high = EEPROM.read (0); // read the first part of the addres
  byte low = EEPROM.read (1); // and the second part
  DMX_addr = word (high, low); // and combine them to the DMX addres
}

 

This example has the advantage that it saves the start address in the EEPROM of the atmega every time it is turned on
situation that with the keys is not necessary
I attach some examples in arduino as well as a simple .EXE to learn how to calculate and know the DMX address

Attachment(s): 

Last Edited: Mon. Apr 27, 2020 - 07:38 PM