Port manipulation on fake Arduino

Hello there, wondering if this is a fake issue?

I have all real arduinos, mostly UNOs and mega2560s. I saw a deal on eBay a couple years ago so I bought some UNOs not realizing they were counterfeit/fake until they arrived. I set them aside.

I have a project that drives a couple of HP attenuators and I guess I blew the real UNO I was using as the chip is hot and one of the ports is high all the time no matter what. I am switching 15v using a transistor on the low side, must have done something wrong, etc.

So I tried the fake and it almost works. I am using PORTB as I need to set and reset the attenuator modules at the same time in order to have a smooth transfer curve.

if for instance, I do this:

// section a on is pin D8, off pin D9
// section b on is pin D10, off pin D11
// section c on is pin D12, off pin D13
// remember PORTB starts at D8 so low bit is D8

PORTB=B011010; // turn off section a&b, turn on section c
delay(100); // wait for relays to transfer
PORTB=0X00; // All relays off

PORTB controls digital pins 8-13. The attenuators I use have a transfer relay that sets three sections, call them a,b,c. So writing B000001 to PORTB sets section a; B000010 resets section a. I want to use port manipulation so that I can pick the set and reset relays at the same time.

it only works once per reset. I can switch any other pins on or off but that specific pin that controls turning on section C (D12) won't work until I reset the board. Even if I write a bunch of 0x00's to PortB or try to reset the DDRB or read PINB, nothing works. Once I write D12 it seems like PORTB is in a hung state, but just that bit. Low thankfully, not stuck high. So it works once and that's it. It is the strangest problems I've ever seen.

I tried everything and have the problem isolated to the port manipulation. Even if I then try to digitalWrite D12, it is hung at low/0. The weird thing is that I had this working last night, turned off the POS fake/clone whatever, and then started having the problem today.

I'm trying to wrap this up this weekend so any ideas short of throwing away the POS would be appreciated.

Jerry

PORTB bits 6 and 7 map to the crystal oscillator so you must avoid changing these.

The "fake" Unos will probably work fine.

You can't change bits 6&7 of PORTB if the crystal oscillator is selected, so don't worry about that. However, it is a good idea to change only only bit of a port at a time, until you have mastered the technique.

To set OUTPUT bit 0 on PORTB, without changing the others:

PORTB |= (1<<PB0);  //substitute PB0 with PB1-5 as needed

Clear OUTPUT bit 0 on PORTB, without changing the others:

PORTB &= ~(1<<PB0); // ditto

Of course, you have to set bits to OUTPUT if you plan to change them. Set bit 0 of PORTB to OUTPUT:

DDRB |= (1<<PB0);

So I guess you are suggesting that doing an assignment to PORTB is not supported? I can do it your way and try it, but I dont see why it would work vs what I'm doing, unless there is a restriction in doing an assigment?

Thanks,

Jerry

Your problem could be related to the order in which you manipulate the DDR and the PORT register and the effect on the pull up resistor or leaving the pin as an input pin.
If using pinMode() and digitalWrite() can’t also do what you want, then your problems may lie elsewhere and not to do with your direct port manipulation.
I would have left bit 6 and 7 alone because these are oscillator pins and your method will affect these, but apparently this according to @jremington is not the problem. Anyway, it is good practice to avoid overwriting unrelated register bits but, other than that, a direct assignment as you have attempted, has the same effect as setting each individual register bit.

So I guess you are suggesting that doing an assignment to PORTB is not supported?

I showed you two examples of doing just that, but perhaps you don't understand the programming language well enough.

Even if I write a bunch of 0x00's to PortB or try to reset the DDRB or read PINB, nothing works.

Since you did not post ALL the code, no one can help solve your specific problem. Where and to what value did you set DDRB?

I set DDRB=B111111; this sets the low order 6 bits of portb, 0:5, 8:13 pins, to output.

The issue here is that the 40 attenuator segment isn't setting when I set just it's 'on' bit. Remember, there is an 'on' relay and 'off' relay. Think of the attenuator segments as as 1, 2, 4 or 10, 20, 40dB. When I try to set 40dB, by setting just that one bit on and the others off, it will not work using port manipulation. But if I set 50, 60 or 70, all of which need the 40 as well, it works. There's nothing wrong in the electronics, I have a scope on the pin. I also can do a digitalwrite to that pin and it works until I set the bit using port manipulation. I understand the code, been coding micros since '76, and there is something funky with these fake boards. If RadioShack was still open I would pop over and buy a genuine UNO.

If I set the bit and turn around and read it, it is correct the first time and then is 0 after, not getting set. I tried two of the clone boards. I have a mega I am going to try today until I can get a real UNO.

Technically, I guess, that by writing a 0x00 to that port i am messing with the higher bits, but why would writing B011010 for 40dB vs B010101 for 70dB make it hang? Maybe the fake boards don't ignore the higher bits. Is there a function on D12 I dont know about? Going to look. I know there is an LED on D13.

I'll post the code later today after I try the other method of setting one bit at a time.

Thanks again,

Jerry

The problem was explained in post #4 and the solution to your incorrect code in post #5.

I set DDRB=B111111; this sets the low order 6 bits of portb, 0:5, 8:13 pins, to output.

Yes your code sets bits 5:0 but it also sets bits 6 and 7 to zero, forcing them to be inputs. Perhaps you don’t think that matters but it does.

Your constant yammering about fake boards is pointless until you’ve decapped the atMega328 and can provide photographic proof the die wasn’t made by Atmel.

Writing zero to b6 and b7 won’t hurt anything unless you’ve disabled the oscillator via fuses.

There is no b8.

I have never heard of a fake Arduino that had a problem with direct writes,assuming it wasn’t completely dead. The Arduino core use them internally for digital write, after all.

I'd have probably done it something like this for demonstration purposes, but the OP must show his code:

DDRB  = ( DDRB  & 0b11000000 ) | 0b00111111 ;  // Pins D8 to D13 output - don't touch bits 6 and 7
PORTB = ( PORTB & 0b11000000 ) | 0b00011010 ;  // 40dB - Pins D8:0 D9:1 D10:0 D11:1 D12:1 D13:0    -  don't touch bits 6 and 7