Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Atmega4809 board definitions #657

Closed
wants to merge 3 commits into from

Conversation

mklemenz
Copy link

This patch should work for the new boards "Nano Every" and "UNO WiFi Rev2" from Arduino.
I have tested receiving IR signals and it works. But since I currently don't have IR emitters/diodes at hand, consider the code necessary for sending signals as experimental.

It fixes the compiler errors mentioned in the issues #639 and #641 as well.

@eclipse1985
Copy link

That's great! I will test it asap. Which are the PINs for send/receive?

@mklemenz
Copy link
Author

for sending it should be the PWM pin D6 on the Arduino Nano Every. if you have a different board, you might need to look up where the chips pin PF4 is routed.

for receiving just pick any analog pin yourself.

looking forward to hearing from your test results.

@eclipse1985
Copy link

I have an Uno WIFI Rev2, as per https://content.arduino.cc/assets/UNOWiFiREV2V4.0_sch.pdf the correct pin should be the D6 too. I'm going to test it in these days.

boarddefs.h Outdated
TCB0.CTRLA = (TCB_CLKSEL_CLKDIV1_gc) | (TCB_ENABLE_bm); \
})

#define TIMER_PWM_PIN 24 /* Uno Every */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the comment say Nano Every

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right! I'll fix it.

also, I got the pin definition wrong. PWM Pin is actually D6 (the 24th pin on the board)

@eclipse1985
Copy link

looking forward to hearing from your test results.

Unfortunately seems that I did not managed to make it work. Receiving is ok, but sending is not. I have tried with all PWM digital PINs on a WIFI Rev2

@mklemenz
Copy link
Author

mklemenz commented Nov 21, 2019

@eclipse1985 I found a mistake I made (thanks you both, you and @AnalysIR, for pointing me in the right direction! ).

would you mind giving it another whirl?

@eclipse1985
Copy link

@eclipse1985 I found a mistake I made (thanks you both, you and @AnalysIR, for pointing me in the right direction! ).

would you mind giving it another whirl?

Unfortunately seems that is not working even with the updated version.

This is the sketch I'm using, where rawData is a tested signal for shutdown my TV. Connected PIN is D6.

#include <IRremote.h>

unsigned int  rawData[67] = {4400,4600, 450,1800, 400,1800, 450,1750, 500,600, 450,750, 400,650, 450,700, 400,700, 400,1800, 450,1750, 450,1800, 450,650, 450,650, 450,700, 400,700, 450,650, 450,650, 450,1800, 450,600, 500,650, 400,700, 450,650, 500,600, 500,700, 400,1850, 400,700, 400,1750, 450,1800, 450,1750, 500,1700, 450,1800, 450,1850, 350};  // UNKNOWN F4BA2989

IRsend irsend;
int freq = 38;
void setup() {}

void loop() {
    irsend.sendRaw(rawData,67, freq);
    delay(2000);
}

@AnalysIR
Copy link
Contributor

AnalysIR commented Nov 21, 2019

It could be the signal you are using. (it looks problematic, in terms of timings)

It appears as Samsung 32 bit Ir signal on AnalysIR. I have cleaned it up for you below.
Try this:
Raw (67): 4500,-4500,560,-1690,400,-1690,560,-1690,560,-560,560,-750,400,-560,560,-560,400,-560,400,-1690,560,-1690,560,-1690,560,-560,560,-560,560,-560,400,-560,560,-560,560,-560,560,-1690,560,-560,560,-560,400,-560,560,-560,560,-560,560,-560,400,-1690,400,-560,400,-1690,560,-1690,560,-1690,560,-1690,560,-1690,560,-1690,560

PS: Also increase the delay to 5 or 10 seconds.

@Seelge
Copy link

Seelge commented Jan 3, 2020

Sending does not work for me, too. I am testing this pull request using the following snippet and an IR-LED driven by a transistor connected to the TIMER_PWM_PIN 6. The pin can be (dis-)connected manually using a physical button. An IR-detector is connected and signals activity using the onboard-LED.

The circuit works when using digitalWrite(..,HIGH): The IR-LED is visibly bright when viewed using a mobile camera, as long as the physical button is pushed, and the detector-LED lights up briefly when pushing/releasing the button.

However using IRsend leaves the IR-LED dark when viewed using a camera and the detector-LED does not signal any activity while pushing/releasing the button.

#include <Arduino.h>
#include "IRremote.h"
// changed C:\users\<USER>\.platformio\lib\IRremote_ID4\boarddefs.h
// according to https://github.com/z3t0/Arduino-IRremote/pull/657/files

#define PIN_DETECT 2
#define PIN_STATUS 13

IRsend irsend;
const bool WIRE_TEST = false; // true uses digitalWrite(..,HIGH) instead of irsend

void setup() {
  delay(2000);
  pinMode(PIN_DETECT, INPUT);
  pinMode(PIN_STATUS, OUTPUT);

  if(WIRE_TEST)
  { // test without irsend
    pinMode(TIMER_PWM_PIN, OUTPUT);
    digitalWrite(TIMER_PWM_PIN, PinStatus::HIGH);
  }
  else
  {
    irsend.enableIROut(38);
    irsend.mark(0);
  }
}

void loop() {
  bool detected = !digitalRead(PIN_DETECT);
  digitalWrite(PIN_STATUS, detected ? PinStatus::HIGH : PinStatus::LOW);
}

@mklemenz
Copy link
Author

mklemenz commented Jan 4, 2020

thanks @Seelge for your analysis and the test code. First the bad news: my board is already built-in into one of my projects and I currently have no chance for doing further tests - so in that regard I fully depend on you/others. I tried to do my best on implementing the platform support based on the code I found in the file ~/.arduino15/packages/arduino/hardware/megaavr/1.8.5/variants/uno2018/variant.c

upon looking into that file once again I saw another possibility for solving the sending issue... would you mind inserting the following code on line number 586 in boarddefs.h
PORTMUX.TCBROUTEA |= PORTMUX_TCB0_bm; \
(2nd line of the definition for TIMER_CONFIG_KHZ ) and give it another try?

oh, and I guess there's one more detail. In "Tools -> Registers Emulation" I guess the value should be set to "None". Again, I'm not sure of the implications if it's not ;)

@Seelge
Copy link

Seelge commented Jan 5, 2020

Thank you for the suggestion, I tried it but the additional line / no register emulation does not seem to have an effect.

@mklemenz
Copy link
Author

mklemenz commented Jan 5, 2020

it seems as if there is something wrong with my timer_enable_pwm and timer_disable_pwm macros. After crawling through atmel documentation sheets again, I think I might have found another possible solution.

the lines 580 and 581 might have to look like this:

#define TIMER_ENABLE_PWM     (TCB0.CTRLB = (TCB_CNTMODE_PWM8_gc | TCB_CCMPEN_bm))
#define TIMER_DISABLE_PWM    (TCB0.CTRLB &= ~(TCB_CNTMODE_PWM8_gc | TCB_CCMPEN_bm))

thanks too for your help! if it works, I'll commit and append it to the pull request.

oh, and would you mind testing a 2nd version of those new definitions?

#define TIMER_ENABLE_PWM     (TCB0.CTRLB |= TCB_CCMPEN_bm)
#define TIMER_DISABLE_PWM    (TCB0.CTRLB &= ~(TCB_CCMPEN_bm))

@Seelge
Copy link

Seelge commented Jan 6, 2020

Progress! With the new TIMER..PWM, the IR-LED lights up and the receiver signals on the transition space->mark. There does not seem to be a functional difference between the two definitions but that may be a limitation of my code snippet.

I compared the behavior to the mega2560 with the same code and there is a different behavior: As long as a mark is sent, the reciever is getting a signal, not only on the change space->mark.

Edit: Just to clarify, with the nano every the receiver only signals on the change space->mark, but the IR LED lights up for as long as the mark is sent. It seems the pin is triggered on but perhaps not with the correct frequency. My receiver is a TSOP4838.

@mklemenz
Copy link
Author

mklemenz commented Jan 6, 2020

good to hear about the progress! regarding the two versions of the macros... technically they are supposed to do the same job; I just wasn't sure if the shorter version suffices.

I don't fully understand your observations. could you elaborate and maybe add a code snippet? is the receiver on the same board?
you mentioned that you have a second board. would you mind running the receiver on the other one? just to confirm/refute frequency issues

@Seelge
Copy link

Seelge commented Jan 6, 2020

Yes, I have a second board. I currently have set up the following circuit twice, one with a nano every and one with a mega2560. Both can send and receive.
Circuit schematic

The only difference is the connected pin for the LEDs, the nano every uses pin 6, and the mega uses pin 9 according to TIMER_PWM_PIN in boarddefs.h.

I added the blue LEDs to make it easiert to see when the IR LED turns on (which I confirmed using a camera). Note that there are six LEDs in total: The builtin LEDs of the nano every and mega2560 are used for the IR receiver.

The code is

#include <Arduino.h>
#include <IRremote.h>
#define PIN_DETECT 2
#define PIN_STATUS 13
IRsend irsend;

void setup() {
  pinMode(PIN_DETECT, INPUT);
  pinMode(PIN_STATUS, OUTPUT);
  irsend.enableIROut(38);
  irsend.mark(0);
}

void loop() {
  bool detected = !digitalRead(PIN_DETECT);
  digitalWrite(PIN_STATUS, detected ? HIGH : LOW);
}

Let M be the mega2560 and N be the nano every, then the behavior is as follows:

  • when not pushing any buttons
    • all LEDs are dark (no one is sending/receiving)
  • when pushing the button in the circuit of M
    • the IR LED and blue LED in the circuit of M are bright (M is sending)
    • the builtin LEDs of both M and N are bright (both are receiving)
  • when pushing the button in the circuit of N
    • the IR LED and blue LED in the circuit of N are bright (N is sending)
    • the builtin LEDs of both M and N flash briefly before going dark again (A)
  • when both buttons are pressed
    • the IR LEDs and blue LEDs in both circuits are bright (M+N are sending)
    • the builtin LED of N is bright, the builtin LED of M is dark (B)

A is a sending problem of the nano every.
B is suspicious but it might hint at a receiving problem of the nano every. Since two signals are interfering with each other, my guess is that behavior of the mega2560 to ignore the signals is correct. I have not yet tested receiving anything beyond a simple long mark/space.

When disabling the receiving code for the nano every, i.e. with an empty loop(), the only change is that the builtin LED of the nano every stays dark.

@Seelge
Copy link

Seelge commented Jan 8, 2020

@mklemenz
When removing the / 2 in line 586, i.e. changing the line to
const uint8_t pwmval = SYSCLOCK / 2000 / (val); \, the different behavior vanishes.

Sending with a simple

void loop() {
  irsend.sendNEC(0xF700FF, 32);
  delay(2000);
}

and receiving with the library example IRrecvDumpV2 works.

Tested with the nano every sending and the mega receiving and vice versa.

@mklemenz
Copy link
Author

mklemenz commented Jan 8, 2020

@Seelge : you're AWESOME!

to be honest, now I'm a bit surprised! a few lines further down (within the same macro) I intentionally set a clock divider to be 2 (TCB_CLKSEL_CLKDIV2_gc)... hence the '/2' in the calculation.

The reason was that the atmega4809 can be clocked up to 20MHz. Considering that the comparator-registers CCMPL and CCMPH each are 8 bits wide and no divider is set, this would not work with 38kHz sending frequency. eg: 20000000/2000/38 equals 263.xxx, which exceeds the 8 Bits.
The arduino guys though set the clock to be working with 16MHz for the UNO Every and UNO WiFi Rev2 boards. this makes the frequency values to be within range even without a clock divider, but I thought to write the code to be independently working with even the highest possible sysclock.

The thing that puzzles me most is that the divider doesn't seem to be working anyway.
Can I ask you for a few further tests with TCB_CLKSEL_CLKDIV1_gc in line number 590 (TCB0.CTRLA = ...)?

@Seelge
Copy link

Seelge commented Jan 9, 2020

Okay, I did some more extensive testing with the following sequence.

void loop()
{
  irsend.sendNEC(0x00000001, 32);  delay(250);
  irsend.sendNEC(0x00000010, 32);  delay(250);
  irsend.sendNEC(0x00000100, 32);  delay(250);
  irsend.sendNEC(0x00001000, 32);  delay(250);
  irsend.sendNEC(0x00010000, 32);  delay(250);
  irsend.sendNEC(0x00100000, 32);  delay(250);
  irsend.sendNEC(0x01000000, 32);  delay(250);
  irsend.sendNEC(0x10000000, 32);  delay(250);
  delay(5000);
}

Test A Sending with the nano every the mega2560 understood but with a high error rate of around 25%, random readings didn't get correctly classified and ended up as other encodings or unknown with bad codes.

Test B Vice versa with the mega2560 sending and the nano every receiving there were no bad readings.

Test C With TCB_CLKSEL_CLKDIV1_gc and the nano every sending the mega2560 didn't understand anything, it was always an unknown encoding with a random code which didn't even repeat when sending the same signal again.
Test D TCB_CLKSEL_CLKDIV1_gc did not affect the other direction: With the nano every receiving every reading was fine.

Then I changed everything back to Test A, nano every sending with TCB_CLKSEL_CLKDIV2_gc and now most readings were fine, with an error rate below 5%.

@afaucher
Copy link

Is this change working? I would love to try it out.

@Seelge
Copy link

Seelge commented Mar 29, 2020

Yes, it worked for me in January with the simple examples above but there might be some unresolved issues. I do not know if a ~5% error rate is typical.

I modified the initial pull request according to the descriptions in this thread but I have not checked whether they are included by now.

@bengtmartensson
Copy link
Contributor

If it interests anyone, I have implemented Atmega4809 support (sending and receiving) in version 1.1.0 of Infrared4Arduino, based on this PR. Available in the Arduino library manager in a few hours ("Infrared").

@ArminJo ArminJo closed this in ffd08fb Jul 4, 2020
ArminJo added a commit that referenced this pull request Jul 4, 2020
@bombarie
Copy link

bombarie commented Jul 28, 2020

This thread has been gold for me, thank you so much @mklemenz and @Seelge for your back and forth messaging.

I took the second option from #657 (comment)

#define TIMER_ENABLE_PWM     (TCB0.CTRLB |= TCB_CCMPEN_bm)
#define TIMER_DISABLE_PWM    (TCB0.CTRLB &= ~(TCB_CCMPEN_bm))

Then the prompt to use TCB_CLKSEL_CLKDIV2_gc instead of TCB_CLKSEL_CLKDIV1_gc from #657 (comment) worked and changed that in line 853:
TCB0.CTRLA = (TCB_CLKSEL_CLKDIV2_gc) | (TCB_ENABLE_bm); \

Now my Nano Every is able to communicate with my video projector (NEC protocol). Thank you!

@ArminJo
Copy link
Collaborator

ArminJo commented Jul 29, 2020

Just one question.
Is the currently implemented version for 4809 not working?
Thanks for feedback.

@bombarie
Copy link

No, I had to change it to the above to get my videoprojector to respond to the commands. Using a Nano Every.

@ArminJo
Copy link
Collaborator

ArminJo commented Aug 3, 2020

@bombarie Can you do me a favor and test the current version 2.6.0. I included your suggested changes, but I have no board to test it.
Thanks
Armin

@ArminJo ArminJo reopened this Aug 3, 2020
@bombarie
Copy link

bombarie commented Aug 3, 2020

@ArminJo All good save for one typo on line 830 of IRremoteBoardDefs.h
It should be
#define TIMER_ENABLE_PWM (TCB0.CTRLB |= TCB_CCMPEN_bm)
instead of
#define TIMER_ENABLE_PWM (TCB0.CTRLB = TCB_CCMPEN_bm)

@ArminJo
Copy link
Collaborator

ArminJo commented Aug 3, 2020

Thanks a lot for QA 👍 Its corrected now in the repo.
If you can positively test it, I will build a new 2.6.1 release.

@bombarie
Copy link

bombarie commented Aug 3, 2020

Yes I positively tested it on my Arduino Nano Every. With the bitwise OR |= syntax correction my video projector responds to commands as expected, with the equals = nothing happens.
Glad to be able to help.

@ArminJo ArminJo closed this Aug 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants