Controlling an AtTiny167 via Serial

Hi There,

For my current project, I would like to have three Microcontrollers in a system, that would be controlled via a GUI on a computer, whether it's with some USB device, or on a separate Raspberry Pi, if that's easier.

The plan is to send commands to the micros via some communication line, that would then locally control driver IC's and the like. The first step could be programming with a command window, and then I'll figure out the GUI (some LabView thing perhaps). The control computer would be at a certain distance from the actual machine that's being controlled.

I would very much like to do this with the AT167, because I'm familiar with it and it has inbuilt serial communication (UART).

Is this even possible or is the UART in that microcontroller just made for programming? If not, would there be another interface that's smarter to use, like SPI?

Thanks in advance
Ivo

The ATTiny167 has a UART (an unusually fancy one for AVRs - it has a nicer baud rate generator and some LIN-related features).

My ATTinyCore ( GitHub - SpenceKonde/ATTinyCore: Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8 ) provides a Serial object that works the same way as Serial on other Arduino-compatible AVR boards. As far as I know, it works (I remember testing it when I implemented it a while back) - if it doesn't, you should create a github issue including demo code that demonstrates the issue.

That is good to know, as I am actually programming using your core (which is awesome btw - thanks a lot buddy).

So I will just hook up my serial sending device to the specific pins and send commands as in, say, the serial monitor, as usual?

Another question, I don't know the protocols well enough, can I use an RS232 port to do this or are the protocols too different?

Yeah - you need to connect TX to RX, RX to TX, and Gnd to Gnd - like any other serial device.

Actual RS232 has voltage levels of +/- 10V; you must use a chip like MAX232 to convert to TTL serial (voltage levels 5v and 0v) to safely connect to arduino. Otherwise, the protocols are identical. Be sure to verify the voltage levels if you have any doubt; unfortunately, it is very common for people, even in official documentation, to refer to TTL serial as RS232.

I was exactly going to fall for that, as everybody always just calls it "serial"

Should be able to verify it by checking voltage from ground to TX pin of the device you're connecting it to (before connecting tx or rx). +5 means it's TTL serial, +10 means RS232

If you don't mind my asking, what made you choose the 167, as opposed to the 1634?

I feel like the 1634 has a more compelling featureset, same package (but 2 more usable pins, since it only has one pair of power pins), same size memory, iirc also cheaper?

Good question, I unfortunately can't give you an answer to that.

I once needed a microcontroller for a thermal control/voltmeter board in a power application. I needed a small microcontroller with enough IO, which I searched with Atmels/Microchips (utterly stupid) search parameter thing, and I suppose the AT167 was simply the first one on the list.

Hey,

just a follow up question:

I wanted to have these commands entered as a string, so that the user could easily type them in on a console-like implementation, say the serial monitor for instance.

I was going to use the Serial.readString() function for that purpose, and just process the string to get the values out.

It works fine on the Arduino Uno, but if I'm trying to compile for the AT167, it returns the error message:
" Class has no member named Serial.readString() "

Am I missing something obvious, do I have to include a header? Or does this function not work for the AT167?

Edit: It is the case with the Serial.setTimeout() function as well

It looks like you have found a bug in my core, I will create an issue for it in github when I'm at a real computer.

It's not immediately obvious why it's not working

Did I? well good thing I'm a bumbling idiot who has no idea how these things work :-[

But I gather it should do, so that function should be part of the core; at least I didn't try calling a function for 2 hours that's not even part of the class.

Yes, it absolutely should work. I'm currently not sure why Stream methods aren't usable with HardwareSerial...

It's sort of beside the point, but String is sort of evil on Arduino boards with small amounts of memory - it's very easy to get yourself into weird memory related issues due to it's use of dynamic memory allocation. It's better to use the techniques described in the Serial Input Basics thread (it's in the "list of useful threads" in the programming section), which use c strings (null terminated char arrays) instead of the String class. Serial.available(), Serial.print() and Serial.read() all work correctly on 167 (or they'd better)

They do, I checked that :wink:

I can't reproduce the problem. I successfully compiled the following minimal sketch for ATtiny167 using both the tip of master branch and 1.1.5 release:

void setup() {
  Serial.readString();
  Serial.setTimeout(42);
}

void loop() {}

@Perlmarmelade please confirm compilation of that sketch fails for you. Which version of ATTinyCore are you using?

I still get the error messages, I'm not sure which version I have as I included it via the link Spence indicated. I believe it must be an earlier version than that. I'm going to update it tomorrow at work, it's getting late round here.
If it helps you, here is my code as I compiled it just a second ago:

/*
  This is the Code for the Yaw Motor Driver

  For EmTronix Sarl
  Ivo Trausch
  last update 29/05/18
*/

#include <avr/pgmspace.h>
#include <stdlib.h>

#define Stop 3
#define Up 4
#define Down 5
#define Left 6
#define Right 7
#define OriginPitch 12
#define LimitPitch 13
#define OriginYaw 14
#define LimitYaw 15

char bootConfirm[] = "    Switchboard booted successfully \n";
char readyConfirm[] = "\n     System is ready to receive instructions \n";
const PROGMEM char bootNotice[] =
  "The system is initialising \n"
  "Instructionset: \n"
  "Type \"move up () degrees\" ; \"move down () degrees\" to tilt \n"
  "    where () is to be replaced with the desired number of degrees to move \n"
  "Type \"turn left () degrees\" ; \"turn right () degrees\" to pan \n"
  "    where () is to be replaced with the desired number of degrees to move \n"
  "Type \"return to zero\" to return to the origin \n"
  "Type \"stop motors\" or press stop button to stop any movement \n"
  ;

String instruction;
int instructionBuffer = 0;
int buttonBuffer = 1;

void setup() {

  pinMode(Stop , INPUT_PULLUP);
  pinMode(Up , INPUT_PULLUP);
  pinMode(Down , INPUT_PULLUP);
  pinMode(Left , INPUT_PULLUP);
  pinMode(Right , INPUT_PULLUP);
  pinMode(OriginPitch , INPUT_PULLUP);
  pinMode(LimitPitch , INPUT_PULLUP);
  pinMode(OriginYaw , INPUT_PULLUP);
  pinMode(LimitYaw , INPUT_PULLUP);
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);

  Serial.begin(19200);
  Serial.setTimeout(200);
  Serial.println(bootConfirm);
/*  delay(1000);
  Serial.print(bootNotice);
  for (int k = 0; k < strlen_P(bootNotice); k++) {
    char miniBuffer =  pgm_read_byte_near(bootNotice + k);
    Serial.print(miniBuffer);
    delay(10);
  }
  delay(1000); 
  Serial.println(readyConfirm); */
  Serial.flush();

}

void loop() {
  if (Serial.available() > 0) {
    instruction = Serial.readStringUntil('\n');
//    Serial.print("instruction: ");
    Serial.println(instruction);
//    delay(250);
    if (instruction == "Red") {
      int a = digitalRead(2);
      digitalWrite(2, !a);
      Serial.println (
        "\nInstruction is recognised as: \n"
        "Red \n"
        "System is processing the instruction\n"
      );
    }
    else if (instruction == "move up 1 degrees") {
      Serial.println ("receiving");
    }
    else {
      Serial.println(instruction);
    }
  }

/*  buttonBuffer = digitalRead (Up);
  if (buttonBuffer == LOW) {
    Serial.println("move up 1 degrees");
    Serial.flush();
    delay(10);
  }
  buttonBuffer = digitalRead (Down);
  if (buttonBuffer == LOW) {
    Serial.println("move down 1 degrees");
    Serial.flush();
  }
  buttonBuffer = digitalRead (Left);
  if (buttonBuffer == LOW) {
    Serial.println("turn left 1 degrees");
    Serial.flush();
  }
  buttonBuffer = digitalRead (Right);
  if (buttonBuffer == LOW) {
    Serial.println("turn right 1 degrees");
    Serial.flush();
  }
*/
}

And this is the dump out of the IDE's bottom window.

In file included from C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\cores\tiny/Arduino.h:165:0,

                 from sketch\Test_Pad.ino.cpp:1:

C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\variants\tinyX7_New/pins_arduino.h:65:0: warning: "PIN_A3" redefined

 #define PIN_A3  ( 4)

 ^

C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\variants\tinyX7_New/pins_arduino.h:64:0: note: this is the location of the previous definition

 #define PIN_A3  ( 3)

 ^

C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\variants\tinyX7_New/pins_arduino.h:66:0: warning: "PIN_A3" redefined

 #define PIN_A3  ( 5)

 ^

C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\variants\tinyX7_New/pins_arduino.h:65:0: note: this is the location of the previous definition

 #define PIN_A3  ( 4)

 ^

C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\variants\tinyX7_New/pins_arduino.h:67:0: warning: "PIN_A3" redefined

 #define PIN_A3  ( 6)

 ^

C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\variants\tinyX7_New/pins_arduino.h:66:0: note: this is the location of the previous definition

 #define PIN_A3  ( 5)

 ^

C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\variants\tinyX7_New/pins_arduino.h:68:0: warning: "PIN_A3" redefined

 #define PIN_A3  ( 7)

 ^

C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\variants\tinyX7_New/pins_arduino.h:67:0: note: this is the location of the previous definition

 #define PIN_A3  ( 6)

 ^

C:\Users\Ivo Trausch\Documents\Arduino\Test_Pad\Test_Pad.ino: In function 'void setup()':

Test_Pad:54: error: 'class HardwareSerial' has no member named 'setTimeout'

   Serial.setTimeout(200);

          ^

C:\Users\Ivo Trausch\Documents\Arduino\Test_Pad\Test_Pad.ino: In function 'void loop()':

Test_Pad:71: error: 'class HardwareSerial' has no member named 'readStringUntil'

     instruction = Serial.readStringUntil('\n');

                          ^

exit status 1
'class HardwareSerial' has no member named 'setTimeout'

You're using ATTinyCore 1.1.2:

Perlmarmelade:

In file included from C:\Users\Ivo Trausch\AppData\Local\Arduino15\packages\ATTinyCore\hardware\avr\1.1.2\cores\tiny/Arduino.h:165:0,

If you update to the latest release of ATTinyCore, 1.1.5 the problem will be solved:

  • Tools > Board > Boards Manager
  • Wait for downloads to finish
  • Scroll down until you see "ATTinyCore by Spence Konde". Click on it.
  • Click "Update"
  • Wait for update to finish'
  • Click "Close".

Oh, well, that would explain it. 1.1.2 is really old...

Well, that was it, runs like a charm now.

Gotta check stuff for updates some time (duh...)