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

A declare block using an Arduino function #66

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

bmcage
Copy link
Contributor

@bmcage bmcage commented Apr 9, 2016

This is the worked out version of a declare as mentioned in Issue #58
A new Arduino block, which creates a function declareUpFront, which is called first in setup()

What do you think? Good approach?

@bmcage
Copy link
Contributor Author

bmcage commented Apr 9, 2016

Here example xml blocks using this construct to create blink no delay:

BlinkNoDelay_nl_xml.txt

@carlosperate
Copy link
Owner

The problem with having an additional "run before run first" is that it doesn't stop the user from adding the same blocks (like the set digital pin #) into that category and have exactly the same problem:

<xml xmlns="http://www.w3.org/1999/xhtml">
  <block type="arduino_functions_ext" id="iSOp+VLyWva~J1n{z#ML" x="87" y="-187">
    <statement name="DECLARE_FUNC">
      <block type="io_digitalwrite_var" id="8Qftah1|L15h7b!T2b}F">
        <field name="PIN">ledPin</field>
        <value name="STATE">
          <block type="io_highlow" id="0LMP%Jn+XwD(_0[VBxzO">
            <field name="STATE">HIGH</field>
          </block>
        </value>
        <next>
          <block type="variables_set" id="`G_y[^sdeT1yFosbwp?4">
            <field name="VAR">ledPin</field>
            <value name="VALUE">
              <block type="io_pin_dig" id="#6sz_o5YKaN:E-hFD5^e">
                <field name="PIN">13</field>
              </block>
            </value>
          </block>
        </next>
      </block>
    </statement>
  </block>
</xml>

producing:

int ledPin;

void declareUpFront() {
  digitalWrite(ledPin, HIGH);
  ledPin = 13;
}

void setup() {
  declareUpFront();
  pinMode(ledPin, OUTPUT);
}

void loop() {
}

I haven't had a chance yet to spend some time thinking about this, so I'm still not quite sure if there is a better way to approach this issue.

@bmcage
Copy link
Contributor Author

bmcage commented Apr 11, 2016

You are right. I already was thinking of possibilities to avoid this.
First, I tried it out, and I like how it looks and behaves compared to my previous define blocks. I put it online, eg:
http://ingegno.be/Manuals/Blockly4Arduino/blockly4Arduino/index_en.html?url=examples/LedUpKidz_01_aan_uit_en.xml

As you say, you can now start to do actual code in this block, and that is not how it should be used. Code that goes up front should be put in setup(), in correct order you want it run.

So, I see following possible improvements:

  1. only allow blocks set variable to in the declare up front part. I cannot think of others that can be needed. Would need to look up how to do that in blockly.
  2. make a specific block which like the if then else block you can add parts to so as to keep on adding as many set variable to as you want. This block could be added once to the code where you want then, though I like the fact you would only be allowed to add such a block to setup. Advantage of this block would be that you then add code up front in the Arduino code also, so no need to use a function.

@carlosperate
Copy link
Owner

Yes, as you were saying, something along the lines of having a "define upfront" on top of "run first" would definitely have to restrict the types of blocks that it allows inside, and as a concept for beginners it doesn't seem very straightforward to understand what it is doing, or why, without somebody explaining the concepts.

Apart from that we also have the issue that if the "arduino setup/loop" functions block is not used (just the blocks dropped on the workspace), then setting a pin number of a digitalWrite/digitalReadto a variable will never produce code that'll compile, as the pinMode will be set in the setup function and the variable pin number would be set in the loop function.
So if we have just the "pseudo-blocks" as:

set LED -> digital pin 1
set digital pin LED to -> HIGH

we would still produce:

int LED;

void setup() {
  pinMode(LED, OUTPUT);
}

void loop() {
  LED0 = 1;
  digitalWrite(LED, HIGH);
}

If we end up already introducing the paradigm of having to "declare" variables before using them, then maybe it will be easier to have a block to just "declare a variable to a value" so that its generator does the code placement in the right level/scope to ensure it works (did you originally have "define variable" a block similar to that?). Or creating the mutator as you proposed would also provide the same type of implementation.

From my point of view, the best possible solution should try to be transparent to the user, even if that complicates the Blockly code slightly. It seems like, so far, we would only run on this issue when assigning pins to variables (can you think of any other block example to suffers from the same problem?), so maybe we could have the variable block or its generator to detect this specific block input and then place the variable assignment at the top of the setup function (providing a dictionary and accessor for that "declaration area", like we do with Blockly.Arduino.addVariable, Blockly.Arduino.addDeclaration, or Blockly.Arduino.addSetup).

@MadTooler
Copy link

I have been playing with my direct code blocks that allow manual entry of code into where ever needed. It is vaguely related, so here is a link to my test site for you to take a look in case it is helpful.

http://www.primalengineering.com/ardublockly_pe/ardublockly/

Load the additional "Code Blocks"

From the Ardublockly menu I added an example that illustrates the basic use "Direct Code Block."

My code is lacking real knowledge of what I am tinkering with, so don't get too concerned if you look at the scripts and see some real junk (baby's first .js project, folks).

Side note... I have noticed the includes miss the library name in the arduino code preview pane even though it properly sends it to the IDE. I will create a new issue for that if it is not already there.

@bmcage
Copy link
Contributor Author

bmcage commented Apr 12, 2016

I see two issues we are mixing, and should pull apart.
One is assigning values to pins via variables.
The other is assigning values to variables, and the order in which that happens.

The declare up front here is meant to allow those in current ardublockly. Messing up the order of variables is a current issues in ardublockly in general which users must learn to avoid (be it by trial and error, or be it by a teacher).
Example of how easy it is: see file in attach (rename to .xml and load in ardublockly)
Wrong_Order_xml.txt

Declare up front block can be usefull in this, as a teacher can instruct to put all defines there. An optional block though, it should not be needed in the core.

The second problem is assigning pins via variables. With this declare up front construct this is possible in my branch, but it is not the solution I want to see. At the moment I assign an integer to a variable, then use that to do digitalwrite.
In the final design, I'd like to add types: DIGPIN, ANAPIN, PWMPIN. Then the pseudo code becomes:

set LED -> DIGPIN 1 ==> this causes LED to be accessible in the dropdown of digitalread/write
set digital pin LED to -> HIGH

So a variable becomes available in the dropdown of setting digital pin if it has type DIGPIN.
In the codeblock of set digital pin LED to -> HIGH we obtain the value of variable, and make sure the code first assigns the variable to the computed value in setup before doing pinMode.
This fixes all issues of how variables can be used to do assign to pin I believe.

With this construct, declare up front is not needed at all, all upfront declares can be done in setup block, it nevertheless might still be usefull, eg if somebody wants to add const later :-)

@bmcage
Copy link
Contributor Author

bmcage commented Apr 12, 2016

As an extra comment, yes I had declare blocks. However, I feel the set variable block must be used instead (which was your suggestion too). If we still go for declare block, it should be like the cast block, so that type referral is working correctly. In pseudocode:

set variable to block <-- declare upfront [value] as [dropdown type]

So the declare upfront block would need to be a block like the cast. The code generator of set variable to block would then need to put the setting of the variable at the top before setup().

All in all, though I did not try out this design yet, having declare in setup with existing blocks seems better to me compared to making a new block. Or if a declare block is present, to have it be a block like I added in this PR and which contains existing setting block

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.

3 participants