Notifications
Clear all

Dancing Tinkerbell for a pirate magician

82 Posts
6 Users
9 Likes
2,650 Views
(@eliza)
Member
Joined: 2 years ago
Posts: 81
Topic starter  

@frogandtoad The full code is hundreds of lines of unrelated LED display code. There is only one pertinent line which is:

 if (rfDriver.recv(inputBuffer, &bufferLength)) { 

When this function call returns true there are chars in the buffer. The buffer is filled from a timer interrupt in the ASK library. This function works perfectly fine. All wires are correct and the program and hardware work.

The problem is when this line ( shown above) is in the main loop and there is also more functionality in the main loop, besides this call.

I'm going to put the call to recv (shown above) into a timer interrupt handler which I just learned to do today.


   
ReplyQuote
frogandtoad
(@frogandtoad)
Member
Joined: 5 years ago
Posts: 1458
 

@eliza

Posted by: @eliza

@frogandtoad The full code is hundreds of lines of unrelated LED display code. There is only one pertinent line which is:

 if (rfDriver.recv(inputBuffer, &bufferLength)) { 

When this function call returns true there are chars in the buffer. The buffer is filled from a timer interrupt in the ASK library. This function works perfectly fine. All wires are correct and the program and hardware work.

The problem is when this line ( shown above) is in the main loop and there is also more functionality in the main loop, besides this call.

I'm going to put the call to recv (shown above) into a timer interrupt handler which I just learned to do today.

I understand how that function works, but posting that on its own does not help us to help you - When you phone a mechanic, the first thing they will ask you is to bring your car in so they can investigate the issue you've described.

When I asked if you could post the full code, I didn't mean to paste it directly into the reply.  Hundreds of lines is not that big, and if you like you can remove any LED code not pertinent to the problem, and just attach the INO file.

If you have some code that you don't want us to see, then that's fine, but it will reduce the amount of help you can get towards solving your problem.

Cheers


   
Ron reacted
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 6988
 

@eliza If no pin then how does data get in or out of the radios. Let me know when you are ready to share the sketch and wiring and be a good listener. 

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2043
 

@zander 

The code he has written does not check the pins the calling function does.

I think he has explained his problem ok but there is just probably missing information for us to work with or our knowledge of this library that is the problem.

loop {

if recv ( params here)

  display results

} // this works

loop {

do something

if recv ( params)

  display results

} // doesn't work

 

 


   
ReplyQuote
Ron
 Ron
(@zander)
Father of a miniature Wookie
Joined: 3 years ago
Posts: 6988
 

@robotbuilder Well that is different from 'no pins'. After that statement I assumed I was dealing with some sort of magical data transfer. 

First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
Sure you can learn to be a programmer, it will take the same amount of time for me to learn to be a Doctor.


   
ReplyQuote
(@eliza)
Member
Joined: 2 years ago
Posts: 81
Topic starter  

@zander The radios are connected to pins 11 on the receiver and pin 12 on the transmitter. The LED grid is connected to pin 3 on the receiver, arduino mega.

The data are captured by calling  ASK_object.recv( inputBuffer, &bufferLength);

I have set up a timer interrupt, which works, to capture radio data this is the ISR:

SR(TIMER4_COMPA_vect){
if (radioDriver.recv(inputBuffer, &bufferLength)) {
Serial.print("Message Received: ");
Serial.println((char*)inputBuffer);
switch(inputBuffer[12]) {
case '1':
tink.SetState(displayCheck);
break;
case '2':
tink.SetState(displayX);
break;
case '3':
tink.SetState(displayCard);
break;
case '4':
tink.SetState(displayCard2);
break;
} // switch char in
} // if radio signal received
} // timer handler

This works just fine.

If my main loop is this:

void loop(){
  blinkLed(LEDPIN);
}

Then every thing works fine. I can blink the LED for 1/2 second, 1 second, 5 seconds. Any length of time. The timer interrupt call to recv() captures the radio data. I don't reference any pin. I call recv()

Another method that works, WITHOUT a timer routine, is this:

loop(){
  blinkLed(LEDPIN);
  dataReady= CheckRadio();
  if(dataReady) {
   dataReady = false;
   Serial.println("Captured radio data!!!!");
  }
}

In this case I can blink the pin at for least up to 2 seconds. The data sent to the radio is stored into the buffer and when I check the radio after a 2 second LED blink, every thing is OK. The data I sent during the execution of the blink are still stored and waiting for retrieval.

If I include this in the main loop, or in something called from the main loop, all is OK:

tink.LightAnLed(tink.currentPosition, 0x20FF00) ;

Now here is the problem, tracked down today at last!! If I include this call:

FastLED.show();

After any amount of processing, then I can no longer fetch the radio transmission.

This is the problem! A call to FastLED.show breaks the radio receiving completely.

I shortened the length of time I was in my display routine by eliminating steps to make it go faster, added the timer interrupt handling of the incoming signal etc. etc. By finally "binary searching" into various scenarios that worked and failed, I broke the "code that broke it" down into the final killer item, and the guilty party is FastLED.show().

Thanks everyone for your suggestions. Many of the suggestions that were, at first glance, "useless," such as "try using millis" weren't useless at all because they were food for thought that led to ideas that I could try. When I looked up what "try using millis" meant it led me to trying the timer interrupt, which worked perfectly. Some of the other suggestions bounced around in my mind as I was trying different strategies.

The problem is not solved. I simply must use the FastLED.show() method, or the entire project is moot. But calling FaslLED.show() completely breaks the utility of the ASK.recv() method. So, does anyone have any idea why a call to FastLED.show would break radio retrieval? That's where I'm going now.

Thanks to all that participated. More to come.

 

 

 


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2043
 

@eliza 

Another piece of the puzzle, using FastLEDS? Or did you mention that earlier.

Anyway a short search makes me think maybe it is an interrupt problem?

https://github.com/FastLED/FastLED/wiki/Frequently-Asked-Questions

"1. I'm losing serial data when I call FastLED.show(), why?
Short version - you're running into problems with interrupts. Long version - see the Interrupt problems wiki page."

 


   
ReplyQuote
(@eliza)
Member
Joined: 2 years ago
Posts: 81
Topic starter  

@robotbuilder I have a way to make it work, using 2 ideas from the forum discussion. I can make a dedicated "radio listener" out of a nano and then use the nano to create hardware interrupts on the mega. I already have a hardware interrupt based system that works for the mega. But, I couldn't generate these interrupts using the machine connected to the buttons when that machine was in a galaxy far away.

There was also a comment somewhere in the stream about "additional processor" and "connecting 2 machines." I forget the details, but this 3 arduino method will definitely work, and I have a lot of the code already written. That idea seemed like left field at that time, but today it is looking real practical.

I don't want to add another arduino as it means finding space for the additional arduino and the battery. Everything has to fit in a fixed space which is already crowded. I would prefer to find a way to make it work with the existing mega. I'm only using 2 pins on the mega!! I chose the mega for greater memory capacity as I need to hold arrays of data that represent the patterns I want to display.

I'm going to dig into the FastLED library to see what I can find out. This is quite perplexing as the connection to the LED grid is simply one wire that goes to arduino pin 3. It simply never occured to me that the LED grid could disable/conflict with the radio, which is on pin 11. Anyone have a notion as to what that could be? It seems that the offending function somehow shuts down pin 11, or changes it from input to output.  ???

Having a look at the github link above now.

This post was modified 2 years ago by Eliza

   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2043
 

@eliza 

https://github.com/FastLED/FastLED/wiki/Interrupt-problems

The FastLED.show() function disables interrupts. Any serial data incoming while interrupts are disabled will be ignored, thus corrupting the data stream.

 


   
Ron reacted
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2043
 

@eliza 

I forget the details, but this 3 arduino method will definitely work, and I have a lot of the code already written.

I had the same thought but figured you wouldn't want to use 3 arduinos 🙂

 

 


   
ReplyQuote
(@eliza)
Member
Joined: 2 years ago
Posts: 81
Topic starter  

@robotbuilder WS2812B is what I'm using, so this link is exactly what I need. Thanks. It's not a "time in my LED display" problem at all, it's this disabling interrupts thing. The ASK.recv() method is timer driven. When I wrote my own timer method all I knew was I couldn't use timer 1, because I could see that ASK was using that. So I just picked timer 4 since I was on the mega. I wrote my timer to check the radio for data about 200 times a second, but in the absence of the led conflict problem I can check the radio as infrequently as every 2 seconds and it still works. That's what had me buffaloed.

I knew that there had to be some logic in the LED grid, since there is just 1 data wire going in, and that single wire gets data to light up any LED, any color. I still have no idea how that grid disables something back on the arduino??? More work to do. From what I see in the link you gave me the dedicated nano radio receiver that generates interrupts on the mega now seems like the easier way to go.

Oh boy, this is a tough one. Thanks again.


   
ReplyQuote
(@eliza)
Member
Joined: 2 years ago
Posts: 81
Topic starter  

@robotbuilder Bingo, that's it. The radio behavior isn't degraded, it is simply gone.


   
ReplyQuote
robotBuilder
(@robotbuilder)
Member
Joined: 5 years ago
Posts: 2043
 

@eliza 

When you first described your project I imagined something more detailed like this 32 led high and width whatever needed.

To enlarge image right click image and select Open link in new window.

tBell

   
ReplyQuote
(@eliza)
Member
Joined: 2 years ago
Posts: 81
Topic starter  

Update on Dancing Tinkerbell

Goal is to create a dancing tinkerbell in a lantern for a pirate magician. Tinkerbell is displayed on a 32 x 8 grid of LEDS. Tinkerbell has 5 states, dancing tinkerbell, and 4 "display a static image" states.

I have a 4 button input with hard wired buttons that create hardware interrupts that works. These interrupts are not affected by the FastLED functions. (Using FastLED to light up the 8 x 32 grid)

This program works like this. I'm showing parts of what works, and there are 4 buttons and 4 interrupts:

//  global
#define SHOWCARDPIN 18
const byte showCardButtonPin = SHOWCARDPIN;

// function definition, 1 of 4, each sets a specific state variable
void ISR1() {
tink.setState(displayCard);
}
 
setup( ) {
...
// 4 of these for 4 pins
pinMode(tinkDanceButtonPin, INPUT_PULLUP); 
attachInterrupt (digitalPinToInterrupt(SHOWCARDPIN),ISR1,FALLING); 
...
}

void loop() {

switch(tink.tinkState) {
   case tinkDancing:
     tink.MakeTinkDance();
   break;
  case displayCard2:
     tink.DrawFourOfDiamonds();
  break;
  case displayX:
    tink.DrawX();
    tink.tinkState = tinkDancing;
  break;
  case displayCheck:
     tink.DrawCheckMark();
    tink.tinkState = tinkDancing;
  break;
  case displayCard:
      tink.DrawKingOfDiamonds();
     tink.tinkState = tinkDancing;
  break;
} // switch

} // loop

I capture a button press via 1 of the 4 interrupts and set a Tinkerbell.state value. The main loop looks at the Tinkerbell.state every time through the loop and does the right thing. Then I restore the state to "Make Tink Dance"

Now I want to hide the buttons in Captain Hook's hook and transmit the button pushes via 433 mhz radios. (Easy, follow Bill's example on dronebot workshop site. Got it working. No problem)

The radio transmission is received by ASK_library.recv( buffer, bufferLength) and this recv function runs on a timer interrupt. (Works like a charm. Easy.)

After I receive a radio transmission I can easily set the state variables as shown above and make the program work, however ...

FastLED.Show() hogs and or disables timer interrupts so the ASK.recv() fails after any call to FastLED.Show( ) and I absolutely must use FastLED.Show because that is the whole purpose of the system, show some dancing lights.

So now, to get the radio transmission, I have a dedicated arduino Nano that receives the radio signal, and this works fine. Now I want to send the received radio signal (really just want to send one byte) to the arduino Mega that is running the main program where the LED grid is displayed.

I thought of using I2C comm from nano to mega but FastLED doco says that this same problem will occur with I2C, so I didn't bother to try it.

I have the working solution, shown above, which is "get a button press on the mega." These interrupts work with the FastLED running.(Is this because FastLED interferes with timer interrupts only? Anyone?)

So: I want to put a voltage on the pin that was used for the button and simulate a button press. I am trying to use a pin on the Nano as digital output, and connect that pin to the pin that was button input on the Mega.

So, here is the question!! Anyone with experience connecting an output pin from one arduino to the input pin of another arduino?

I thought it would be as simple as leaving the code intact and connecting the 2 pins, and connecting the grounds of the 2 arduinos. A web site recommended putting a high value resistor on the line to prevent some kind of burn out problem if the 2 arduinos started at different times. So I did that. I presume that the digital input doesn't need current, it needs voltage. So I ran the connection through a 100 k ohm resistor. When I put HIGH on the pin on the Nano side I expect Mega to see HIGH on its pin. This seems to me like I've simulated a button press.

I know I'm getting radio input and sending that to output. I can see "sanity check" leds lighting up.

I can't detect any input at the mega.

I know that the mega hardware interrupt is working correctly, IF I can get it to run.

I expected putting the pulse on the output pin on the Nano to put a voltage on the pin on the mega and generate the hardware interrupt just like I pushed a physical button. In this case the button pusher will be the invisible man, but the signal from the Nano is high for a full half second as if the person held the button down for a half second, then I write LOW as if the person released the button.

Anyone ever connected arduino1 out to arduino2 in ??

 


   
ReplyQuote
(@eliza)
Member
Joined: 2 years ago
Posts: 81
Topic starter  

@robotbuilder This image is great, but we're using a 32 x 8 inside a lantern. Not enough pixels for this detail. Tinkerbell is a green diamond dropping pixie dust. She dances and then answers question with yes or no and then also reveals a chosen card. It won't be particularly amazing, just fun and amusing.


   
ReplyQuote
Page 4 / 6