Trying to understand the Extension Builder's coding concepts


#1

Hi Everyone

This is indeed jolly hard stuff for an old brain to absorb and to master - it’s a bit like wading through treacle!

I am about twentyfive pages into what, I hope, will be a reassuring and simple explanation of what mBlock’s ‘Extension Builder’ actually does and the best way to start using it successfully. After much cross-referencing of all of the help files, being totally misguided by some of the information available here on the Forum and trying the provided, but mostly unhelpful extension examples; together with a lot of experiments (with many aborted attempts & frequently frustrating failures) ; I have eventually come up with my own method of creating a set of working blocks that amazingly DO work.

As you can see from the image below, I have three blocks that do run the code that I have specified in the declare: editor and then activated by running my run-once-only coding sequence of named procedures in the setup: editor of the Upload transcode tab for each block.

As stand-alone blocks, they each run perfectly when downloaded into mBlock’s ‘Extension Centre’ and then uploaded into an mBot 1.0 robot as shown in the next image. I have not incidentally, added or tweaked any other code anywhere else on any other of the software’s many tabs and their sub-settings (other than specifying Arduino C as the transcoding language).

The next two images show a little more detail of the transcode from the two blocks shown above:

extension%20blocks%20test%204

Together, these two blocks (uploaded in ‘Upload’ mode and starting with the ‘when mBot (mcore) starts up’ hat block) add their codes together and transcode correctly causing the robot to sound it’s buzzer, flash its LEDs and turn left, right and back to the position it started from.

BUT - If the two blocks that define the buzzer and LEDs are used together (or with other similar block types from the blocks palette list) then the code that they generate duplicates the definition of any connected Me modules & Me device components that have been already specified in the transcode, and these double-entries of common code that cause the code to crash and not upload correctly. Why, and how can I fix this?

The two blocks shown above do work together - but only because they have no definition conflicts. Could anyone who knows about these things kindly explain what bit of extra coding I need to add (& where) to prevent such duplication when similar block types, as described above, are joined into one programme.

A second problem zone occurs here too. If I add a third block, let’s say my ‘Wiggle Waggle’ block and set it above the first two blocks in my demonstration, then whilst it doesn’t have any coding conflicts with the other blocks the lowest ‘Wiggle Waggle’ block seems to be ignored and does not add a further three ‘twisting’ lines of code (one set at the top and one set at the bottom) of the setup section of the resultant transcode. Any ideas regarding both of these problems would be gratefully received.

Apart from these small glitches, that’s one small step for mankind completed; and any further help or support in my endeavours on this front would be most welcome.

Many thanks

Lindsay Rooms


Question: How do I make an extension for mBot?
#2

@Best_codes & @makeblock.lindingxin Is there anything that either of you can advise me on here?


#3

Based on the photos, I can’t determine much. Could you copy and paste the Arduino C as text into a post? (Select it and press CTRL and C).
Also, only part of the code should go into the “declare” section on the extension builder. Some should, the rest should be in the code section.
If you can give me more info, I can probably help you.

Thanks for your time,
Best_codes


#4

Hi @Best_codes

Thanks for your help. Shown below as requested is the whole Arduino C transcode dump:

// generated by mBlock5 for mBot
// codes make you happy

#include <MeMCore.h>
#include <Arduino.h>
#include <Wire.h>
#include <SoftwareSerial.h>

MeBuzzer buzzer;
MeRGBLed rgbled_7(7, 2);

void No_LEDs(){
rgbled_7.setColor(0,0,0,0);
rgbled_7.show();
}
void Red_LEDs(){
rgbled_7.setColor(0,255,0,0);
rgbled_7.show();
}
void Green_LEDs(){
rgbled_7.setColor(0,0,255,0);
rgbled_7.show();
}
void Blue_LEDs(){
rgbled_7.setColor(0,0,0,255);
rgbled_7.show();
}
void White_LEDs(){
rgbled_7.setColor(0,255,255,255);
rgbled_7.show();
}
void Flash_LEDs(){
Red_LEDs();
_delay(0.5);
Green_LEDs();
_delay(0.5);
Blue_LEDs();
_delay(0.5);
No_LEDs();
}
void Play_Note_C4(){
buzzer.tone(261.6, 250);
_delay(0.1);
}
void Play_Note_D4(){
buzzer.tone(293.6, 250);
_delay(0.1);
}
void Play_Note_E4(){
buzzer.tone(329.6, 250);
_delay(0.1);
}
void Play_Note_F4(){
buzzer.tone(349.2, 250);
_delay(0.1);
}
void Play_Note_G4(){
buzzer.tone(392, 250);
_delay(0.1);
}
void Play_Note_A4(){
buzzer.tone(440, 250);
_delay(0.1);
}
void Play_Note_B4(){
buzzer.tone(493.9, 250);
_delay(0.1);
}
void Play_Note_C5(){
buzzer.tone(523.2, 250);
_delay(0.1);
}
void Play_Octave(){
// N.B. starts at middle C - on a piano, the fourth C key from the left
Play_Note_C4();
Play_Note_D4();
Play_Note_E4();
Play_Note_F4();
Play_Note_G4();
Play_Note_A4();
Play_Note_B4();
Play_Note_C5();
}
MeDCMotor motor_9(9);
MeDCMotor motor_10(10);

void Twist_Left(){
move(3, 40 / 100.0 * 255);
_delay(0.25);
move(3, 0);
}
void Twist_L_R(){
move(4, 40 / 100.0 * 255);
_delay(0.5);
move(4, 0);
}
void Twist_Right(){
move(3, 40 / 100.0 * 255);
_delay(0.35);
move(3, 0);
}
void move(int direction, int speed) {
int leftSpeed = 0;
int rightSpeed = 0;
if(direction == 1) {
leftSpeed = speed;
rightSpeed = speed;
} else if(direction == 2) {
leftSpeed = -speed;
rightSpeed = -speed;
} else if(direction == 3) {
leftSpeed = -speed;
rightSpeed = speed;
} else if(direction == 4) {
leftSpeed = speed;
rightSpeed = -speed;
}
motor_9.run((9) == M1 ? -(leftSpeed) : (leftSpeed));
motor_10.run((10) == M1 ? -(rightSpeed) : (rightSpeed));
}

void _delay(float seconds) {
long endTime = millis() + seconds * 1000;
while(millis() < endTime) _loop();
}

void setup() {
Flash_LEDs();
Play_Octave();
White_LEDs();
_delay(0.25);
Green_LEDs();
_delay(0.25);
No_LEDs();
Twist_Left();
Twist_L_R();
Twist_Right();
}

void _loop() {
}

void loop() {
_loop();
}

In the Extension Builder, the declare: section of one block contains the two definitions:
MeBuzzer buzzer;
MeRGBLed rgbled_7(7, 2);

In the declare: section of the second block are the two motor definitions:
MeDCMotor motor_9(9);
MeDCMotor motor_10(10);

I also put all of my own self-defined Functions in the declare: section of each of these blocks. Should such self-defined Functions be written in the code: section instead? As you can see in the transcoded Arduino C code above, they do appear where you would expect them to.

The setup: section of the first block contains my run-once Function calls:
Flash_LEDs();
Play_Octave();
White_LEDs();
_delay(0.25);
Green_LEDs();
_delay(0.25);
No_LEDs();

The setup: section of the second block contains my run-once Function calls:
Twist_Left();
Twist_L_R();
Twist_Right();

There is nothing in the code: section or the loop; section of either block.

As I said in my original post, these extension blocks do work OK, but it is the double-entries of common code that cause the code to crash and not upload correctly if similar-type blocks are used together. The two blocks I showed do work together OK as the the transcoded Arduino C code demonstrates - but only because they have no definition conflicts. I think that Functions or variables that are shared by multiple blocks are referred to as common functions or variables. How can I define and modify them in a centralized way by configuring what I think is refered to as common code?


#5

Move the code in the setup section to the code section and see if that helps. mBlock will auto put anything in the code section in the setup() or loop() code.
It might seem strange, but just give it a try.
It may work, it may not.

Thanks for your time,
Best_codes


#6

@Best_Codes Thanks for your idea of moving code from the setup: section to the code: section. I can confirm that this worked OK and the codes ran OK and as before. There was one success and one failure here.

Moving my run-once-only code into the code: section solved the second problem that I outlined in my original post. This concerned adding a third block - (a second ‘Wiggle Waggle’ block) which was ignored the second time and did not add a second lot of three ‘twisting’ lines of code into the resultant transcode. Now, as you can see from the screenshot below, using multiple blocks does work:

three%20blocks%20test

On startup my test mBot now wiggles left and right, plays an octave on the buzzer, flashes and then wiggles left and right once more.

The first problem that I outlined has not been solved - this occurs if two blocks of similar block types from the blocks palette list are used together in a script. The code that they generate duplicates the definition of any connected Me modules & Me device components that have been already specified in the transcode and these double-entries of common code cause the code to crash and not upload correctly.

I’m still working on this too - using a common code or middleware setting somewhere in the Extension Builder may be the way forward here …?


#7

Take your code from the declare section. Copy it, delete it, press “OK”, and click save. Now switch to the “Transcode Settings” tab:
image
Click where my cursor is in the picture:


After the code:
//( declare //)

Paste your declare code.
Click “OK”, then save, and repeat this for your other declare codes.

Thanks for your time,
Best_codes


#8

Thanks again for your ideas. I’ve just tried moving my declare section codes into the transcoding template as suggested (see below):

After doing this and downloding the .mext file, the blocks code in mBlock didn’t work and the transcode showed no declaration of either MeBuzzer buzzer; or MeRGBLed rgbled_7(7, 2);

To test that my blocks would work together, I added two more blocks to ‘force’ the declaration of these - see below:

Forced%20declarations

These two blocks did declare the required MeBuzzer buzzer; & MeRGBLed rgbled_7(7, 2); lines of code and my three test blocks in that sequence then uploaded correctly into my test mBot.

N.B. I left all of my own defined functions still in the declare section for each block - should I have added all of these into the transcoding template too?


#9

Hmm…. I guess just move your code back to the declare section.
I research to see if I can find another solution.


#10

Your declare code is where the picture shows “//Your declare code”, right?


#11

Hi @Best_codes

Thanks for your continued support with this problem.

As to your query, yes, you can see that i am (was) using the declare: section if you look at the first picture of my original post. I will be working on this over the weekend too. I don’t really know how to do this but I am thinking that I need to add a bit of JavaScript somewhere - a common code extension event handler such as '“extension.onLoad” perhaps?

I have looked at the mBot device .mext file to see how similar blocks work but that hasn’t really given me many clues. I’ve tried adding a ‘Live mode handler (onRun)’ sequence like the one shown below - but this doesn’ work:

async (args, app, device, block) => {
if (isNaN(args.LED_Visible) || Number(args.LED_Visible) <= 0) {
return;
}
await MeRGBLed_7()
.position(Number(args.LED_Position))
.rgb(args.LED_Colour)
.runAwait(Number(args.LED_Visible) * 1000);

await MeRGBLed_7()
    .position(Number(args.LED_Position))
    .rgb('#000000')
    .runAwait();

}

I’m totally out of my depth with studying the mBot device blocks (which seem really complicated) - they seem to rely on Sensorium being loaded and the Snippets section contains definitions of all Me modules together with several source files being loaded.


#12

for info. … another test completed (& another failure to report!).

After looking at the mBot device blocks .mext file that I have, once again. I noticed that whilst mBot’s buzzer is declared as:
MeBuzzer buzzer;

The on-board LEDs were declared as:
['MeRGBLed rgbled_7(7, 2);] and not as: MeRGBLed rgbled_7(7, 2);

So, I tried this in the extension blocks that I have been using and ['MeRGBLed rgbled_7(7, 2);] was not recognised and crashed the code.

… Onwards and upwards!

regards

Lindsay


#13

Here’s what I recommend:
Create a new block (command block) called “Setup extension”.
Under the “Upload transcode” section of this block, paste this code in the “declare” category:

MeBuzzer buzzer;
MeRGBLed rgbled_7(7, 2);

void No_LEDs(){
rgbled_7.setColor(0,0,0,0);
rgbled_7.show();
}
void Red_LEDs(){
rgbled_7.setColor(0,255,0,0);
rgbled_7.show();
}
void Green_LEDs(){
rgbled_7.setColor(0,0,255,0);
rgbled_7.show();
}
void Blue_LEDs(){
rgbled_7.setColor(0,0,0,255);
rgbled_7.show();
}
void White_LEDs(){
rgbled_7.setColor(0,255,255,255);
rgbled_7.show();
}
void Flash_LEDs(){
Red_LEDs();
_delay(0.5);
Green_LEDs();
_delay(0.5);
Blue_LEDs();
_delay(0.5);
No_LEDs();
}
void Play_Note_C4(){
buzzer.tone(261.6, 250);
_delay(0.1);
}
void Play_Note_D4(){
buzzer.tone(293.6, 250);
_delay(0.1);
}
void Play_Note_E4(){
buzzer.tone(329.6, 250);
_delay(0.1);
}
void Play_Note_F4(){
buzzer.tone(349.2, 250);
_delay(0.1);
}
void Play_Note_G4(){
buzzer.tone(392, 250);
_delay(0.1);
}
void Play_Note_A4(){
buzzer.tone(440, 250);
_delay(0.1);
}
void Play_Note_B4(){
buzzer.tone(493.9, 250);
_delay(0.1);
}
void Play_Note_C5(){
buzzer.tone(523.2, 250);
_delay(0.1);
}
void Play_Octave(){
// N.B. starts at middle C - on a piano, the fourth C key from the left
Play_Note_C4();
Play_Note_D4();
Play_Note_E4();
Play_Note_F4();
Play_Note_G4();
Play_Note_A4();
Play_Note_B4();
Play_Note_C5();
}
MeDCMotor motor_9(9);
MeDCMotor motor_10(10);

void Twist_Left(){
move(3, 40 / 100.0 * 255);
_delay(0.25);
move(3, 0);
}
void Twist_L_R(){
move(4, 40 / 100.0 * 255);
_delay(0.5);
move(4, 0);
}
void Twist_Right(){
move(3, 40 / 100.0 * 255);
_delay(0.35);
move(3, 0);
}
void move(int direction, int speed) {
int leftSpeed = 0;
int rightSpeed = 0;
if(direction == 1) {
leftSpeed = speed;
rightSpeed = speed;
} else if(direction == 2) {
leftSpeed = -speed;
rightSpeed = -speed;
} else if(direction == 3) {
leftSpeed = -speed;
rightSpeed = speed;
} else if(direction == 4) {
leftSpeed = speed;
rightSpeed = -speed;
}
motor_9.run((9) == M1 ? -(leftSpeed) : (leftSpeed));
motor_10.run((10) == M1 ? -(rightSpeed) : (rightSpeed));
}

Remove all declare code from the other blocks and the //(declare//) section on the transcode template.

Then, when you make your code for mBot, put the new block first:
image

See if that works any better. I’m sorry it’s taking so long to solve the problem!

Thanks for your time,
Best_codes


#14

That sounds like a very sensible idea. I was vagely thinking of something similar myself a couple of days ago. Not quite what I wanted, but as a work-around concept it should be OK. I’ll report back when I try it out tomorrow.

Other than the very useful Yuque webpages:
https://www.yuque.com/makeblock-help-center-en/extension-builder/create-extension
and Makeblock’s: newish Help Hub pages:
https://education.makeblock.com/help/category/mblock-extension-builder/extension-configuration/
and Makeblock’s original mBlock 5 help file:
https://www.mblock.cc/doc/en/developer-documentation/develop-configuration.html

Is there anywhere else that you are aware of from where Extension Builder guidance can be sought / learned?


#15

Not that I’m aware of.


#16

Hi @Best_codes
I tried it: …


… and whilst this does allow all of my blocks to work very well together when headed by my new ‘Initialise mBot’s Devices & My Functions’ block; as I suspected it doesn’t solve the problem of adding ‘real’ mBlock blocks of a similar type. If any blocks from the blocks palette list are used together with my new block in a script then the code that they generate still duplicates the definition of any connected Me device components that have been already specified.

Ok, I do have a workaround solution for now, but I would still like to solve the problem of these double-entries causing the code to crash. These block experiments are not a project in their own right, but a way to examine and understand the nuances of coding within the Extension Builder.

To that end, I would welcome contributions from other Extension Builders and especially from the experts within @makeblock_product @makeblock123 @tech_support @makeblock.lindingxin.

many thanks as always

Lindsay


#17

You can still make your code, copy the Arduino C, and paste in the “Code With Arduino C” section.


Then you can remove the unnecessary declare and press upload!


#18

Yes I could - but that’s not what I’m trying to do. As I said in my last post, these block experiments are not a project in their own right, but a way to examine and understand the nuances of coding within the Extension Builder.


#19

OK, thanks!


#20

Come on you Extension Builders, share your knowledge…

… together we will gain much.

‘All for one, and one for all’.