Set G code value based on Code variable.

Sorry but I never had to face this puzzle before.

I’m using this code as a base for a project.

// Example for M5Stack StepMotor Module (I2C verison)
// 2018/6/27 JimmyLai
#include <M5Stack.h>
#include <Wire.h>

void setup() {
  // put your setup code here, to run once:
  M5.begin();
  Wire.begin();
  Serial.begin(115200);
  m5.Lcd.setTextColor(WHITE, BLACK);
  m5.Lcd.setTextSize(2);
  m5.lcd.setBrightness(100);
  M5.Lcd.setCursor(4, 10);
  M5.Lcd.println("StepMotor Test: 0x70/0x71");
  M5.Lcd.setCursor(4, 30);
  M5.Lcd.println("Press A: 0x70");
  M5.Lcd.setCursor(4, 50);
  M5.Lcd.println("Press B: 0x71");
}

void SendByte(byte addr, byte b) {
  Wire.beginTransmission(addr);
  Wire.write(b);
  Wire.endTransmission();
}

void SendCommand(byte addr, char *c) {
  Wire.beginTransmission(addr);
  while ((*c) != 0) {
    Wire.write(*c);
    c++;
  }
  Wire.write(0x0d);
  Wire.write(0x0a);
  Wire.endTransmission();
}

void loop() {
  if (digitalRead(39) == LOW)  // A button
  {
    while (digitalRead(39) == LOW) delay(1);
    SendCommand(0x70, "G1 X20Y20Z20 F500");
    SendCommand(0x70, "G1 X0Y0Z0 F400");
  }
  if (digitalRead(38) == LOW)  // B button
  {
    while (digitalRead(38) == LOW) delay(1);
    SendCommand(0x71, "G1 X20Y20Z20 F500");
    SendCommand(0x71, "G1 X0Y0Z0 F400");
  }
  if (digitalRead(37) == LOW)  // C button
  {
    while (1) {
      SendCommand(0x70, "G1 X0Y0Z0 F500");
      SendCommand(0x71, "G1 X0Y0Z0 F500");
      delay(1000);
      M5.Lcd.print(".");
      delay(1000);
      SendCommand(0x70, "G1 X5Y5Z5 F500");
      SendCommand(0x71, "G1 X5Y5Z5 F500");
      delay(1000);
      M5.Lcd.print(".");
      delay(1000);
    }
  }
  // Get Data from Module.
  Wire.requestFrom(0x70, 1);
  if (Wire.available() > 0) {
    int u = Wire.read();
    if (u != 0) Serial.write(u);
  }
  Wire.requestFrom(0x71, 1);
  if (Wire.available() > 0) {
    int u = Wire.read();
    if (u != 0) Serial.write(u);
  }
  delay(1);
  // Send Data to Module.
  while (Serial.available() > 0) {
    int inByte = Serial.read();
    SendByte(0x70, inByte);
    SendByte(0x71, inByte);
  }
}

Is it possible to dynamically Set the G code “F” value based on a variable?

Is it possible to dynamically Set the G code "F" value based on a variable?

Yes. You could build the string (note, NOT String) to be sent using strcat() or sprintf() with the "F" value controlled by an if or possibly by selecting it from an array based on the value of the variable.

Might help for understanding sprintf sprintf - C++ Reference

Thanks, One thing that confuses me is that all example result in a space between the word and the converted value i.e

F 100 instead of F100,

Is this just to make it clear or will I break the code by dropping the space so that

F%d will make F100.

Sorry, not sure how to better word it as I have never dealt with sprintf before.

My code section (probubly wrong).

void Speed()
  {
    char buffer [50];
    int speed = 0;
    speed=sprintf (buffer,"F%d " ,buffer,speed);
  }

void loop() 
  {
  // put your main code here, to run repeatedly:
  if (digitalRead(39) == LOW)  // A button
  {
    while (digitalRead(39) == LOW) delay(1);
    SendCommand(0x70, "G1 X0Y0Z20 F500");
  }

It is the SendCommand(0x70, "G1 X0Y0Z20 F500"); that I need to be SendCommand(0x70, "G1 X0Y0Z20 F%d");

Varify throws no errors but I'm still confused about sprintf

I guess what i need is a mentor here to just double check my code.

The first thing to note is that you have declared buffer and speed in the function so they will only be available in that function

Here is an example using global variables

char buffer[30];

void setup()
{
  Serial.begin(115200);
  makeCommand("G1 X0Y0Z20 F", 500);
  makeCommand("SOMETHING F", 1234);
  for (unsigned int x = 10; x < 20; x++)
  {
    makeCommand("SOMETHING F", x);
  }
}

void loop()
{
}

void makeCommand(char * messageBody, unsigned int fValue)
{
  sprintf(buffer, "%s%u", messageBody, fValue); //format string and unsigned int
  Serial.println(buffer);
}

UKHeliBob:
The first thing to note is that you have declared buffer and speed in the function so they will only be available in that function

Opps, I thought it looked wrong when I typed it.

UKHeliBob:
Here is an example using global variables

char buffer[30];

void setup()
{
 Serial.begin(115200);
 makeCommand(“G1 X0Y0Z20 F”, 500);
 makeCommand(“SOMETHING F”, 1234);
 for (unsigned int x = 10; x < 20; x++)
 {
   makeCommand(“SOMETHING F”, x);
 }
}

void loop()
{
}

void makeCommand(char * messageBody, unsigned int fValue)
{
 sprintf(buffer, “%s%u”, messageBody, fValue); //format string and unsigned int
 Serial.println(buffer);
}

Is the buffer size an actual limit of 1 to 30?
I can’t seam to find the correct google string to get the answer.
I want the buffer to be able to accept up to 999 but have a cap of around 400 (future project I’m working on)
After I makeCommand can I then send Command?

char buffer[30];

void setup()
{
  Serial.begin(115200);
  makeCommand(0x70, "G1 X0Y0Z20 F", 500);
  makeCommand("SOMETHING F", 1234);
  for (unsigned int x = 10; x < 20; x++)
  {
    makeCommand("SOMETHING F", x);
  }
}

void loop()
{
}

void makeCommand(char * messageBody, unsigned int fValue)
{
  sprintf(buffer, "%s%u", messageBody, fValue); //format string and unsigned int
  Serial.println(buffer); //Prints to console?
  Lcd.println(buffer); //Prints to screen
  SendCommand(buffer); // Sends to I2C port

}

Huh?

'makeCommand' was not declared in this scope

Post the code that generated that error

Sorry, It help to remember these things!

//M5Stack powered Photography Turntable using M5Stepper Motor Controller.
//Turntable stepper is connected to the Z port.
#include <M5Stack.h>
#include <Wire.h>
#include <stdio.h>

char buffer[30];

void setup() 
{
  M5.begin();
  Wire.begin();
  Serial.begin(115200);
  makeCommand("G1 X0Y0Z20 F", 500);
  makeCommand("SOMETHING F", 1234);
  for (unsigned int x = 10; x < 20; x++)
  {
    makeCommand("SOMETHING F", x);
  }
  m5.Lcd.setTextColor(WHITE, BLACK);
  m5.Lcd.setTextSize(2);
  m5.lcd.setBrightness(100);
  M5.Lcd.setCursor(4, 10);
  M5.Lcd.println("M5Stack Photography Turntable.");
  M5.Lcd.setCursor(4, 30);
  M5.Lcd.println("Press A: 0x70");
  M5.Lcd.setCursor(4, 50);
  M5.Lcd.println("Press B: 0x71");
 
}

void SendByte(byte addr, byte b) 
{
  Wire.beginTransmission(addr);
  Wire.write(b);
  Wire.endTransmission();
}

void SendCommand(byte addr, char *c) 
{
  Wire.beginTransmission(addr);
  while ((*c) != 0) {
    Wire.write(*c);
    c++;
  }
  Wire.write(0x0d);
  Wire.write(0x0a);
  Wire.endTransmission();
}


void loop() 

  {
  // put your main code here, to run repeatedly:
    char buffer [50];
    int speed = 0;
    speed=sprintf (buffer,"F%d " ,buffer,speed);
  if (digitalRead(39) == LOW)  // A button
  {
    while (digitalRead(39) == LOW) delay(1);

  }
 void makeCommand(char * messageBody, unsigned int fValue)
{
  sprintf(buffer, "%s%u", messageBody, fValue); //format string and unsigned int
  Serial.println(buffer); //Prints to console?
  M5.Lcd.println(buffer); //Prints to screen
  SendCommand(buffer); // Sends to I2C port
}

 
 
 // Get Data from Module.
  Wire.requestFrom(0x70, 1);
  if (Wire.available() > 0) {
    int u = Wire.read();
    if (u != 0) Serial.write(u);
  }
  Wire.requestFrom(0x71, 1);
  if (Wire.available() > 0) {
    int u = Wire.read();
    if (u != 0) Serial.write(u);
  }
  delay(1);
  // Send Data to Module.
  while (Serial.available() > 0) {
    int inByte = Serial.read();
    SendByte(0x70, inByte);
    SendByte(0x71, inByte);
  }
}

You have tried to declare your MakeCommand function in the middle of the loop function. Move it, perhaps to the bottom of the sketch.

Well, after a bit of bouncing around I got it to compile.

#include <M5Stack.h>
#include <Wire.h>
#include <stdio.h>
#include <M5ez.h>
#include <ezTime.h>
#include "images.h"

#define MAIN_DECLARED

void setup() {
  #include <themes/default.h>
  #include <themes/dark.h>
  ezt::setDebug(INFO);
  ez.begin();
  Serial.begin(115200);
  makeCommand("G1 X0Y0Z20 F", 500);
  makeCommand("SOMETHING F", 1234);
  for (unsigned int x = 10; x < 20; x++)
  {
    makeCommand("SOMETHING F", x);
  }
}

void loop() {
  ezMenu images;
  images.imgBackground(TFT_BLACK);
  images.imgFromTop(40);
  images.imgCaptionColor(TFT_WHITE);
  images.addItem(sysinfo_jpg, "Photo Turntable", sysInfo);
  images.run();
}
char buffer[30];



void makeCommand(char * messageBody, unsigned int fValue)
{
  sprintf(buffer, "%s%u", messageBody, fValue); //format string and unsigned int
  Serial.println(buffer);
}

however it uses to much space.

sprintf() uses a lot of memory

Try this approach instead, but no promises

void setup()
{
  Serial.begin(115200);
  Serial.println(makeCommand("G1 X0Y0Z20 F", 500));
  Serial.println(makeCommand("SOMETHING F", 1234));
    for (int x = 10; x < 30; x++)
    {
      Serial.println(makeCommand("SOMETHING F", x));
    }
}

void loop()
{
}

char * makeCommand(char * messageBody, int fValue)
{
  char outputBuffer[50] = {'\0'};
  char fValueBuffer[5] = {'\0'};
  strcpy(outputBuffer, messageBody);  //copy the message body to the output buffer
  itoa(fValue, fValueBuffer, 10);   //convert the F value to a string
  strcat(outputBuffer, fValueBuffer); //concatenate the F value with the message
  return outputBuffer;
}