Notifications
Clear all

Dancing Tinkerbell for a pirate magician

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

Hi,

I have a 32 x 8 LED grid in a lantern. I am making a green dancing tinkerbell that drops pixie dust move across the grid. (arduino mega) I have a 4 button set up hidden in Capt'n Hook's hook. I want to send 1,2,3 or 4 to the mega with the 433 mhz radios

Everything works, up to a point.

Here is the main loop:

void loop() {
  
  // buffer full when data received
  if (rfDriver.recv(inputBuffer, &bufferLength)) { 
  // set tink's state based on the incoming message
  // no need for local strings
  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
   

  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
 } // if radio signal received

} // loop

If I comment out the switch I can capture data from the transmitter and display the message.

If I use the switch and begin the MakeTinkDance procedure I no longer get any radio messages. I presume that it takes so long to return from MakeTinkDance (about 10 seconds) that the radio receive buffer is flushed and I have to read the buffer within some window of opportunity that I am missing.

I'm using the RH ASK library as illustrated by Bill in his example with these radios.

Anyone familiar enough with this library to offer a suggestion?

Thanks


   
Quote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2535
 
Posted by: @eliza

Hi,

If I comment out the switch I can capture data from the transmitter and display the message.

It's not obvious which of the two 'switch' statements you mean here.

Is it possible that you're getting some value other than 1-4 from the radio ? Try putting a default case on the first switch and print whatever value comes through, just in case it's not valid.

Anything seems possible when you don't know what you're talking about.


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

Oops, sorry. I mean the switch that contained the call to MakeTinkDance. If I comment out the call to MakeTinkDance then I get the correct values from the radio. The problem is not bad data coming from the radio. I can capture my button presses at the transmitter and correctly send the correct data.

I can capture the data on the receiving end and use it correctly. What I can't do is capture the radio signal if I include the call to MakeTinkDance.  MakeTinkDance draws a green diamond shaped pattern, and then drops yellow pixie dust. Every 3rd movement of the diamond I move the pixie dust. When I get to the end of the grid I reverse directions and go back so the diamond is moving left to right, then right to left.

Originally I was moving the entire length of the grid and back again before checking for radio data. That took about 10 seconds

Tonight I modified the code so that I send Tink's position to the MakeTinkDance rountine. Then I draw just one diamond and return the new location where Tink will dance to next. This cuts the time of the function down by a huge amount, (eliminating 2 big for loops).

Next I cut out the dropping and moving of the pixie dust to try to pick up some time. Right now MakeTinkDance() just draws one diamond and then returns, so very little time is spent in that routine.

The problem is not waiting 10 seconds between calls to radio.recv() The calls to radio.recv() are happening pretty quickly now, but perhaps still not quick enough. I generate a few random numbers so that Tink dances in a jerky path and light 5 pixels (LEDs).

I saw a comment on another site that said that the ASK library has a builtin timer interrupt so you don't have to do anything to get the read buffer filled, just go about your business and the code in the library will get the data.

If I completely eliminate the call to MakeTinkDance I get the signal. Then I enter some other long routines depending on the incoming data. During the execution of these functions I can't get any radio signals, and I don't want to. I want these functions to complete before checking for a new state.

Just had a thought. I'm going to try "light just one LED" and see if that works. Perhaps there is a conflict between ANY led lights and the radio signal.

 


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

If I simplify MakeTinkDance to where I light just one LED, increment the position counter and return I can make it work, so there is no hardware conflict between the radio and the LED grid nor address conflict with any pins. (I did have a pin address conflict between the radio and the buttons which I solved.)

It seems to be the speed at which I can execute MakeTinkDance and return that is critical. I looked through the ASK code looking for a "how long to wait" variable and couldn't find anything right away, nor could I find any thing that looked like "flush the buffer after this long" I'd like to keep the radio buffer valid for an extended length of time.


   
ReplyQuote
Will
 Will
(@will)
Member
Joined: 3 years ago
Posts: 2535
 

@eliza 

I believe that the ASK library uses a timer interrupt to operate. If you're using a timer or an interrupt in MakeTinkDance, you should maybe check to make sure there's no conflict.

Anything seems possible when you don't know what you're talking about.


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

@will I'm not using any interrupts. I believe that the ASK library uses a timer interrupt. I saw a comment to that effect on another site. The problem is the function I am calling between checks for radio data runs too long. I'm trying to find out how/when the radio library checks for data, and how long it holds it. I know data are sent. If my MakeTinkDance function does too much the receive fails. I don't know why the data aren't just held in the buffer for as long as I want, (within reason). I shortened my routine by a lot and it still failed.


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

@eliza 

I am not sure exactly what rf modules you are using and would have to purchase my own if I don't have them on hand to figure out how to deal with lost data.

My suggestion is that you use millis() and change makeTinkDance() to updateTinkDance() and call it at fixed intervals in the loop.  The updateTinkDance would display the next frame and reset the tinkState when done. Although called continuously it would only do the dance if the tinkState was set.

 

 


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

@robotbuilder What does "use millis" mean?

How does changing the name of the function have an effect?

What does the type of rf modules have to do with it? They work perfectly well.

When the function is shortened to a single LED light up I receive the transmission.

The library documentation says, "Call the recv often enough to get the data. Put it in the main loop" It is in the main loop and I'm trying to call it as often as possible given the other tasks I need to do. But there's no info as to how often "often enough" is.

"call it at fixed intervals in the loop" That's what I'm doing. I make a specific function call (which is running at some fixed length. There's only one path of execution through the function) and then I check recv immediately thereafter. If the duration of the function call is too long the recv method produces no result. ??? I don't see why the data isn't saved in the buffer until I empty it. ??? Where does the data go? and why? The transmissions are happening and I presume that the timer interrupt occurs behind the scenes no matter what other processing I might be doing. ???


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

@eliza 

What does "use millis" mean?

https://forum.arduino.cc/t/using-millis-for-timing-a-beginners-guide/483573

It is a way of executing a function x times per unit of time.

How does changing the name of the function have an effect?

It doesn't. I would have to see your makeTinkDance() to change the code. The change in name is only to reflect a change in what the function does, from running an animation from start to end before returning and instead just updating to the next frame of the animation and then returning to check other things like a new number in the rf buffer store.

What does the type of rf modules have to do with it? They work perfectly well.

It has to do with being able to recreate your setup. Often the answer is found in what you don't say not what you do say. Again and again I see posts that think that all that is required for an answer is the information that is given. The worst I have seen is "my program doesn't work, why?" Or, "I wired it up as directed and it doesn't work, why." Without seeing the program or the wiring who would know?  It becomes a long list of posts trying to guess what is going on.

Also what you are doing might be of interest to others. How do you do your animations on the 32x8 display for example.

 

 


   
ReplyQuote
ron bentley
(@ronbentley1)
Member
Joined: 2 years ago
Posts: 385
 

@robotbuilder @eliza

Without fully understanding the entire code and its flow I suspect that you have hit the nail on the head. Too much processing time would appear to be being consumed in the makeTinkDance() function, sounds like its blocking processing.

Ron B

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


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

@ronbentley1 

I have used the nRF24L01 module transceivers but not the 433 MHz Modules.
I assume this is the tutorial @eliza has used.
https://dronebotworkshop.com/433mhz-rf-modules-arduino/
The method Bill is using is ASK (amplitude shift keying) which gives an on/off value. You can vary how long to keep it on or off.
Bill says RadioHead "is a very complex library, we will only be using the Amplitude Shift Keying code from it". So if you wanted you could write your own code to transmit and receive data and not even use a library.
He also writes that the loop repeats and our message is sent over and over so I don't see how it would vanish unless there is a limit to how many times the message is repeated. I see @eliza is using a 12 character buffer. So I guess that means it fills up with the same character 12 times. But this is what I mentioned earlier without all the information and the code and hardware it is a guessing game taking for ever to nail the problem.

I don't have the modules myself so I can't work out what is happening and the local Jaycar only offers these modules which look different.

To enlarge an image, right click image and choose Open link in new window.

ZW3102 wireless modules receiver 433mhzImageMain 300
ZW3100 wireless modules transmitter 433mhzImageMain 515

 


   
ron bentley reacted
ReplyQuote
ron bentley
(@ronbentley1)
Member
Joined: 2 years ago
Posts: 385
 

@robotbuilder 

It looks like you have a good handle on this and from what you say there is a degree on complexity involved. 

I cant make any sensible suggestions I'm afraid as the technology is not within my experience so I will butt out!

Regards

Ron B

Ron Bentley
Creativity is an input to innovation and change is the output from innovation. Braden Kelley
A computer is a machine for constructing mappings from input to output. Michael Kirby
Through great input you get great output. RZA
Gauss is great but Euler rocks!!


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

@robotbuilder  After posting I see that this reply is really related to what Ron Bently posted but I replied to robotbuilder.

  I am using the modules from the tutorial you linked because they are small and the coding is absolutely trivial.

I have used nRf24L01 with the reliable data gram package as Bill shows with the robot car. I think that method would work as the software uses a "send until you get confirmation" technique. I didn't use this hardware/software combo because it took up a lot of space and seemed like tremendous overkill. All I want is to capture a single digit, that comes only every minute or so. The apparatus needs to be hidden in a Captain Hook costume hook.

The only reason I'm using a 14 char buffer is I preceeded the data with "Tinkerbell" so as to check that I wasn't getting any spurious data from radio noise. My intention was to check that the package contained "My header" and then capture the digit off the end of the string. For the initial test I sent "Tinkerbell: 1" When I use a simple test over and over loop it works perfectly. As soon as I use "do something, then check for radio data" it fails. My original "do something" loop took about 10 seconds so I chopped that into a series of small steps that take less than a second but found that I needed to pare it down to a tiny step that doesn't accomplish anything near what I want to do.

I can light up a single pixel and then check for the single, but I want to draw a 5 pixel diamond, then some random pixie dust pixels, and then scatter the previously dropped pixie dust ... Just drawing the 5 pixel diamond apparently takes too much time.

My next plan is to imbed the radio driver into the tinkerbell object and check for data after every single light a pixel event. This is a real pain. I think:

void LightLed( int pixelToLight) {

  lightItUp( pixgelToLight);


  radio.recv( params here)


  if (dataIn)


    set "data ready" class variable


    capture radio buffer to class variable


    return "discontinue function" variable


else


   return "keep going"

 

Might work

All the comments are appreciated. Keep 'em coming. Thanks

This post was modified 2 years ago by Eliza

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

@eliza 

When I use a simple test over and over loop it works perfectly. As soon as I use "do something, then check for radio data" it fails.

Your receiver code would not be taking in any more data after the MakeTinkDance() function is called.  So if you pressed a button during the dance it would be physically impossible to receive that character because the receiver code is not running. Is that the problem? If however the transmitter keeps repeating the last button press then the moment the dance is finished the receiver should again start getting the character being sent. Without seeing the sending and receiving protocol it is all guess work. Later I will see if I can find more information on how the characters are encoded and what is the start and end codes for sending a series of characters. There is always the option of writing your own transmit and receive software. It is just an on/off software switch where you can hold the switch down for as long as required or leave it off for as long as required depending on how you want to code the data. The receiver code has to have some way to determine the start of the transmission so it doesn't start reading it in the middle somewhere.

 


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

@eliza Just a quick observation here, if it wasn't a typo, 10 secs is an eternity, 10 msecs is more realistic. If you have a function that is time critical like reading a coms line, then that function has top priority. I have some familiarity with that, I used to be responsible for reading all the stock exchange feeds in North America, we never dropped a single bit. I am not in a position at the moment for a while to look into this more deeply, but if the diamond and dust have to suffer in order to make sure you don't drop data, then so be it, OR use a second processor that can run asynchronously for the display elements. Good luck.

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
Page 1 / 6