Map Decimal Numbers to double byte?

Hello

Im using a MCP23017 to drive leds. The Leds are behind plastic numbers, and light them up. Number 0-7 are on GPIO A and 8-9 are on GPIO B.

To set the registers i use the function "OutputDisplay", and i have to use a DECIMAL number matching the BINARY output.

Eg. 1 would turn GPIOA 1 on, which turns LED0 on
256 would turn GPIOA8 on, which turns LED7 on
to control 0-9 i need to set both registers, since 8-9 are on GPIOB

OutputDisplay(1,1);
Output Displa(2,1);

void OutputDisplay(int address, int value, int value2){
  Wire.beginTransmission(address);
  Wire.write(0x12);
  Wire.write(byte(value));
  Wire.write(byte(value2));
  Wire.endTransmission();
}

This works fine.

But now, i need a function to turn a 2 digit DECIMAL number, in suitable output function.
eg. The decimal Number of "50" would result in the following two output function:

OutputDisplay(adress1,32,0);
OutputDisplay(adress2,0,0)

the Number 12 would result in

OutputDisplay(adress1,2,0);
OutputDisplay(adress2,4,0);

So i kinda need a mapping from decimal to my needed special-decimal number, like 1 = 2, 3 =5;
And this should be stored on a 16bit, variable, and then the function Output display should split it up.

Can someone help me to get this working and reliable?

and i have to use a DECIMAL number matching the BINARY output.

What do YOU mean by decimal number? Probably not the same thing that the boobs at Microsoft think.

How did you decide that 50 mapped to 32 and 0? That 12 mapped to 2 and 4?

PaulS:
What do YOU mean by decimal number? Probably not the same thing that the boobs at Microsoft think.

How did you decide that 50 mapped to 32 and 0? That 12 mapped to 2 and 4?

i get an integer, and if i print to serial monitor it is like 19,20,21,23,24,25

this should split to two seprate integers, for 19 : int rightNr = 1 , int leftNr 9.

Then there should be a function convert it to:

int theNumber = 19;
prepare(int theNumber);

value1 value2
0 = BIN 1 = 00000000 00000001
1 = BIN 2 = 00000000 00000010
2 = BIN 4 = 00000000 00000100
3 = BIN 8 = 00000000 00001000
4 = BIN 16 = 00000000 00010000
5 = BIN 32 = 00000000 00100000
6 = BIN 64 = 00000000 01000000
7 = BIN 128 = 00000000 10000000
8 = BIN ??? = 00000001 00000000
9 = BIN ??? = 00000010 00000000

then

OutputDisplay(adress1,value1,value2);

resulting in:

void OutputDisplay(int address, int value, int value2){
  Wire.beginTransmission(address);
  Wire.write(0x12);
  Wire.write(byte(value));
  Wire.write(byte(value2));
  Wire.endTransmission();
}

Then why not just bit shift the values…

byte upper = 1UL << (val / 10); // ex 25 / 10 = 2, then 1UL << 2 = 4
byte lower = 1UL << (val % 10); // ex. 25 % 10 = 5, then 1UL << 5 = 32;

void OutputDisplay(int address, int value){
  Wire.beginTransmission(address);
  Wire.write(0x12);
  Wire.write( byte(1UL << (value / 10)) ); // when direct instead of assigning it to a variable
  Wire.write( byte(1UL << (value % 10)) );
  Wire.endTransmission();
}

HazardsMind:
Then why not just bit shift the values…

byte upper = 1UL << (val / 10); // ex 25 / 10 = 2, then 1UL << 2 = 4
byte lower = 1UL << (val % 10); // ex. 25 % 10 = 5, then 1UL << 5 = 32;

void OutputDisplay(int address, int value){

Wire.beginTransmission(address);
  Wire.write(0x12);
  Wire.write( byte(1UL << (value / 10)) ); // when direct instead of assigning it to a variable
  Wire.write( byte(1UL << (value % 10)) );
  Wire.endTransmission();
}

But? i need eg. 19 to split in 2 transmissions to different adresses the “1” from 19, should be transmissed to ADRESS1, and the “9” from 19 to ADRESS2

Ans shift values, what if value is 0 ?, for 0 the output has to be 1, since 0, is a LED to, indicating the 0

Where does the 19 come from ?

Maybe you want to convert an integer into its string representation and then split the string into two characters. I think sprintf() is the function to create a string representation of a number.

However the alternative is that you want to split the integer 19 into the 10s value and the ones value - both still being integers. You do that like this

int bigVal = 19;
int tensDigit = bigVal / 10;
int onesDigit = bigVal % 10;  // the modulus operator gives the remainder.

...R

Robin2:
Where does the 19 come from ?

Maybe you want to convert an integer into its string representation and then split the string into two characters. I think sprintf() is the function to create a string representation of a number.

However the alternative is that you want to split the integer 19 into the 10s value and the ones value - both still being integers. You do that like this

int bigVal = 19;

int tensDigit = bigVal / 10;
int onesDigit = bigVal % 10;  // the modulus operator gives the remainder.




...R

Awesome thats what i looked for :smiley:

Now, how can i convert the onesDigit and tensDigit to a 16bit variable, like i showed above?

sgt_johnny:
Awesome thats what i looked for :smiley:

Now, how can i convert the onesDigit and tensDigit to a 16bit variable, like i showed above?

In that example they are already stored in int type variables. Those are 16 bit variables. I don't see what more there is to convert.

So does value1 control the high byte, I am very confused as to what you are asking?

What about something like this?

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  for (byte i = 0; i < 10; i++) // 0 - 9
  {
    int data =  (1UL << (i % 10));
    Serial.print( data >> 8, BIN); // high byte
    Serial.print(" ");
    Serial.println(data & 0xFF , BIN); // low byte
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

Delta_G:
In that example they are already stored in int type variables. Those are 16 bit variables. I don't see what more there is to convert.

Yes right, but the "stored number" in the 16bit variable is not suitable for output if there is a 1 Stored in a 16bit variable, thenn the variable is 00 00 00 00 00 00 00 01. If i send this to the MCP-Chip, it will turn GPIO A 1 on which is wrong.

If i send a byte of data to the MCP, each bit of the byte, controls one output. since i need 10 outputs, and one GPIO has only 8, i need to use both

                          value1     value2
 0   = BIN 1      = 00000000 00000001
 1   = BIN 2      = 00000000 00000010
 2   = BIN 4      = 00000000 00000100
 3   = BIN 8      = 00000000 00001000
 4   = BIN 16    = 00000000 00010000
 5   = BIN 32    = 00000000 00100000
 6   = BIN 64    = 00000000 01000000
 7   = BIN 128  = 00000000 10000000
 8   = BIN ???   = 00000001 00000000
 9   = BIN ???   = 00000010 00000000

check this table.

The function from Robin2 splits my decimal number i revice into 2 digts

int bigVal = 19;
int tensDigit = bigVal / 10;
int onesDigit = bigVal % 10;  // the modulus operator gives the remainder.

And now i need to convert tensDigit and onesDigit to output. eg if tensDigit is "5", it has to be converted to 32, that GPIOA 6 can turns HIGH.

Do you understand?

eg if tensDigit is “5”, it has to be converted to 32, that GPIOA 6 can turns HIGH.

you mean like “1 << 5” ?

AWOL:
you mean like “1 << 5” ?

No, this does not work with 8-9, because you cant shift more than 8 to the left? because then the byte is full?

I need 2 bytes, because 8-9 has to be on GPIO B, which has a separate byte.

Or am i wrong?

No, this does not work with 8-9, because you cant shift more than 8 to the left? because then the byte is full?

So start a new byte.

I’ve no idea if you’re right or wrong.
You said you wanted to to turn a 5 into 32.
1 << 5 was the most obvious way that came to mind (I assumed you didn’t want 5 * 6.4)

When I look at your Reply #6 and then at all the stuff that has followed that I reckon that the real problem is that you have not told us what you really need. And perhaps you are not too clear about that yourself.

I suspect it is time to go back to basics and lay out your requirement clearly.

...R

Okay, i try to describe as precise as possible

Im having two rows of glass-plates, they have blue paint on it, some of the glass is non-colored, in shape of numbers from 0-9. Behind each Number is a LED/Lightbulb, to illuminate the number. The two rows are under each other. Looks like this

Row1: [0] [1] [2] ...
Row2: [0] [1] [2] ...

Each row is connected to an MPC23017 Port expander:

GPIOA1: LED0
GPIOA2: LED1
GPIOA3: LED2
GPIOA4: LED3
GPIOA5: LED4
GPIOA6: LED5
GPIOA7: LED6
GPIOA8: LED7

GPIOB1: LED8
GPIOB2: LED9

To turn the Leds on, i have to use the following code:

Wire.beginTransmission(MCP_ADRESS);
  Wire.write(0x12);
  Wire.write(byte(valueGPIOA));
  Wire.write(byte(valueGPIOB));
  Wire.endTransmission();

I use two MCP23017 to control both Rows.

via reading Serial input (cant be changed) i recive a number i have to display, lets say 19, or 01, or 55, can be any between 00 and 99.

I need to split this number, because the first (1 from 19, 0 from 01, 5 from 55) should be displayed in ROW1 and the second should be displayed in ROW2

If i send the number "9" from 19 directly to the MCP, it would turn high GPIOA1 and GPIOA4 because 9 in binary is 00001001.
Turning these outputs high, would illuminate the digits 0, and 3 on the first row. which is completely wrong.

in case of 9, GPIOB2 has to turn high, to illuminate the digit 9 on the glass-plate.

So the thing to do is:
1.) recive 2-digit decimal number from serial, name it "theInput" [done!]
2.) split "theInput" into 2 variables, "digitTens" and "digitOnes" (16bit)
3.) prepare these 2 variables, to correct output
4.) output digitTens to MCP_1, GPIOA = digitTens lower 8bits, GPIOB = digitTens higher 8bits
5.) output digitTens to MCP_2, GPIOA = digitOnes lower 8bits, GPIOB = digitOnes higher 8bits

I think my answer in reply #12 is still valid.

2.) split "theInput" into 2 variables, "digitTens" and "digitOnes" (16bit)

You've been shown how to do this. It's a simple divide operation and a modulo operation.

4.) output digitTens to MCP_1, GPIOA = digitTens lower 8bits, GPIOB = digitTens higher 8bits

That is a simple operation to, using highByte() and lowByte().

sgt_johnny:
So the thing to do is:
1.) recive 2-digit decimal number from serial, name it "theInput" [done!]
2.) split "theInput" into 2 variables, "digitTens" and "digitOnes" (16bit)
3.) prepare these 2 variables, to correct output
4.) output digitTens to MCP_1, GPIOA = digitTens lower 8bits, GPIOB = digitTens higher 8bits
5.) output digitTens to MCP_2, GPIOA = digitOnes lower 8bits, GPIOB = digitOnes higher 8bits

Reading this thread, I have seen good solutions to 2 and 3. 4 and 5 are hardware dependent but should follow the I2C code that you posted very closely.

It's strange. You seem to be almost there already, yet you can't express what part you don't get. It would behoove you to cobble together whatever code you have and post it in its entirety.

PaulS:
You've been shown how to do this. It's a simple divide operation and a modulo operation.
That is a simple operation to, using highByte() and lowByte().

yes but how do i convert the "tensDigit" and "onesDigit" to my specific code?