Page 235

PWM colours breadboard layout

Page 236 - teletype emulation

#include <SoftwareSerial.h> #define RX_PIN 11 #define TX_PIN 13 SoftwareSerial serialT(RX_PIN, TX_PIN); // new serial object char buff[80]; byte bufPos = 0; void setup() { Serial.begin(115200); serialT.begin(300); // Choose something more sensible delay(1000); serialT.println("Ready?"); serialT.println("10 PRINT \"HELLO WORLD\""); serialT.println("20 GOTO 10"); serialT.println("30 END"); serialT.println("RUN"); } void loop() { char nChar; if(serialT.available()){     nChar = serialT.read();     if(nChar == '\r' || nChar == '\n') {      if(bufPos > 0) {         Serial.println(buff);      }      bufPos = 0;      memset(buff, '\0', 80); // clear buffer     } else {      buff[bufPos] = nChar;      bufPos++;     } } }

Pages 236 and 237 - PDP emulation

#include <SoftwareSerial.h> #define RX_PIN 11 #define TX_PIN 13 SoftwareSerial serialT(RX_PIN, TX_PIN); // new serial object char buff[80]; byte bufPos = 0; void setup() { Serial.begin(115200); serialT.begin(300); // Choose something more sensible delay(1000); serialT.println("Ready?"); serialT.println("10 PRINT \"HELLO WORLD\""); serialT.println("20 GOTO 10"); serialT.println("30 END"); serialT.println("RUN"); } void loop() { char nChar; if(serialT.available()){     nChar = serialT.read();     if(nChar == '\r' || nChar == '\n') {      if(bufPos > 0) {         Serial.println(buff);      }      bufPos = 0;      memset(buff, '\0', 80); // clear buffer     } else {      buff[bufPos] = nChar;      bufPos++;     } } }

RS232

The amazing Ben Eater has posted a great video on implementing an RS232 interface for his breadboard computer. Click to see the video here. While he is dealing with the voltage range of the RS232 spec he also has to manage the serial protocol - nicely handled by the library functions we made use of in the code above. Check it out if you are wondering how serial works without a clock signal (even if settings have to be agreed).

page 240

PWM colours breadboard layout

Page 241 - master

#include <Wire.h> #define SLAVE_ADDRESS 42 int reqPin = 1; void setup() { Serial.begin(115200); Wire.begin();         } void loop() { int remoteVal; Wire.beginTransmission(SLAVE_ADDRESS); Wire.write(reqPin); // sends low order byte Wire.endTransmission(); Wire.requestFrom(SLAVE_ADDRESS, 2); while(Wire.available()) {     byte bl = Wire.read(); // read low byte     byte bh = Wire.read(); // read high byte     remoteVal = bh;     remoteVal = remoteVal << 8;     remoteVal += bl; } Serial.print("Analog pin "); Serial.print(reqPin); Serial.print(" value: "); Serial.println(remoteVal); reqPin++; if(reqPin > 3) {reqPin = 1;} delay(1000); }

Pages 242 - slave

#include <Wire.h> #define I2C_ADDRESS 42 int reqVal; void setup() { Serial.begin(115200); Wire.begin(I2C_ADDRESS); Wire.onReceive(receiveData); Wire.onRequest(sendData); } void loop() { // This Arduino can be doing many other things here } void receiveData(int byteCount){ while(Wire.available()) {     reqVal = Wire.read(); } } void sendData() { int retVal = 0; switch(reqVal) {     case 1:      retVal = analogRead(A1);      break;     case 2:      retVal = analogRead(A2);      break;     case 3:      retVal = analogRead(A3);      break; } Serial.println(retVal); Wire.write(retVal); retVal = retVal >> 8; Wire.write(retVal); }

I2C Projects

I used an I2C interface to communicate with a module created from an HC-SR04 ultrasonic sensor sitting on top of a 9g servo motor.
This sonar scanner was controlled by an Arduino Nano running a software state machine. The module was operated and interrogated from another Arduino over an I2C master/slave link.
The mini project was covered by two blog posts. Part 1 developed the sonar module and part 2 saw the I2C link to a controlling Arduino.


Page 244

PWM colours breadboard layout

Pages 245 and 246

#include <SPI.h> #include <SD.h> struct ddata{ float area; unsigned long time; int val; } demo = {22145.679, 45871298, -32766}; union dbytes{ struct ddata data; byte bytes[10]; } going, coming; void setup() { Serial.begin(115200); going.data = demo; if (!SD.begin()) {     Serial.println("Card failed, or not present");      return; } if(SD.exists("datatest.dat")){     SD.remove("datatest.dat"); // start with a new file } Serial.println("Creating File"); File dataFile = SD.open("datatest.dat", FILE_WRITE); if(dataFile) {     dataFile.write(going.bytes, 10);     dataFile.close(); } else {     Serial.println("Error opening file");     return; } if(SD.exists("datatest.dat")) {     dataFile = SD.open("datatest.dat", FILE_READ);     if(dataFile) {      dataFile.read(coming.bytes, 10);      dataFile.close();      if(coming.data.area == demo.area) {         Serial.print(coming.data.area, 3);         Serial.println(": Area checked");      }      if(coming.data.time == demo.time) {         Serial.print(coming.data.time);         Serial.println(": Time checked");      }      if(coming.data.val == demo.val) {         Serial.print(coming.data.val);         Serial.println(": Int val checked");      }     } else {      Serial.println("Error reopening File");     } } else {     Serial.println("Where is the File?"); } }

Page 248

PWM colours breadboard layout

Pages 248 and 249

#define data0 6 #define data1 7 #define data2 8 #define data3 9 #define data4 10 #define data5 11 #define data6 12 #define data7 13 #define strobe A0 #define ack A1 #define busy A2 char testMessage[] = "HELLO PARALLEL WORLDS"; void setup() { pinMode(strobe, OUTPUT); digitalWrite(strobe, HIGH); pinMode(ack, INPUT_PULLUP); pinMode(busy, INPUT_PULLUP); pinMode(data0, OUTPUT); pinMode(data1, OUTPUT); pinMode(data2, OUTPUT); pinMode(data3, OUTPUT); pinMode(data4, OUTPUT); pinMode(data5, OUTPUT); pinMode(data6, OUTPUT); pinMode(data7, OUTPUT); } void loop() { for(int i = 0, j = strlen(testMessage); i < j; i++) {     writeByte(testMessage[i]); } writeByte('\n'); delay(3000); } void writeByte(byte b){ while(digitalRead(busy) == HIGH) {     // wait a bit } digitalWrite(data0, b & 1); digitalWrite(data1, b & (1 << 1)); digitalWrite(data2, b & (1 << 2)); digitalWrite(data3, b & (1 << 3)); digitalWrite(data4, b & (1 << 4)); digitalWrite(data5, b & (1 << 5)); digitalWrite(data6, b & (1 << 6)); digitalWrite(data7, b & (1 << 7)); digitalWrite(strobe, LOW); while(digitalRead(ack) == HIGH) {     //wait for acknowledge } digitalWrite(strobe, HIGH); }

Page 250 and 251

#define data0 6 #define data1 7 #define data2 8 #define data3 9 #define data4 10 #define data5 11 #define data6 12 #define data7 13 #define strobe A0 #define ack A1 #define busy A2 void setup() { Serial.begin(115200); pinMode(strobe, INPUT); pinMode(ack, OUTPUT); digitalWrite(ack, HIGH); pinMode(busy, OUTPUT); digitalWrite(busy, HIGH); pinMode(data0, INPUT); pinMode(data1, INPUT); pinMode(data2, INPUT); pinMode(data3, INPUT); pinMode(data4, INPUT); pinMode(data5, INPUT); pinMode(data6, INPUT); pinMode(data7, INPUT); } void loop() { readByte(); } byte readByte() { digitalWrite(ack, HIGH); while(digitalRead(strobe) == HIGH){     digitalWrite(busy, LOW); } digitalWrite(busy, HIGH); byte b = digitalRead(data0) +      (digitalRead(data1) << 1) +      (digitalRead(data2) << 2) +      (digitalRead(data3) << 3) +      (digitalRead(data4) << 4) +      (digitalRead(data5) << 5) +      (digitalRead(data6) << 6) +      (digitalRead(data7) << 7); digitalWrite(ack, LOW); delay(5); // hold ack LOW for a bit Serial.print((char)b); }

Page 252

void setup() { #ifdef USE_PORTS DDRC &= ((1 << DDC1) | (1 << DDC2)); // A1 & A2 INPUT DDRC |= (1 << DDC0); // A0 output PORTC |= ((1 << PORTC1) | (1 << PORTC2)); //A1 & A2 PULLUP DDRB |= B00111111; // D8 -D13 set for OUTPUT DDRD |= B11000000; // D6 & D7 for OUTPUT #else pinMode(strobe, OUTPUT); digitalWrite(strobe, HIGH); pinMode(ack, INPUT_PULLUP); pinMode(busy, INPUT_PULLUP); pinMode(data0, OUTPUT); pinMode(data1, OUTPUT); pinMode(data2, OUTPUT); pinMode(data3, OUTPUT); pinMode(data4, OUTPUT); pinMode(data5, OUTPUT); pinMode(data6, OUTPUT); pinMode(data7, OUTPUT); #endif }

Page 253

void writeByte(byte b){ #ifdef USE_PORTS while(PINC & B00000100){ // while busy HIGH } #else while(digitalRead(busy) == HIGH) {     // wait a bit } #endif #ifdef USE_PORTS byte regCpy = (PORTB >> 6); PORTB = (regCpy << 6) | (b >> 2); regCpy = (PORTD << 2); PORTD = (regCpy >> 2) | (b << 6); #else digitalWrite(data0, b & 1); digitalWrite(data1, b & (1 << 1)); digitalWrite(data2, b & (1 << 2)); digitalWrite(data3, b & (1 << 3)); digitalWrite(data4, b & (1 << 4)); digitalWrite(data5, b & (1 << 5)); digitalWrite(data6, b & (1 << 6)); digitalWrite(data7, b & (1 << 7)); #endif #ifdef USE_PORTS PORTC ^= B00000001; // strobe LOW while(PINC & B00000010){ // Wait for ack } PORTC |= B00000001; // strobe HIGH #else digitalWrite(strobe, LOW); while(digitalRead(ack) == HIGH) {     //wait for acknowledge } digitalWrite(strobe, HIGH); #endif }

Page 254

void setup() { Serial.begin(115200); DDRC |= ((1 << DDC1) | (1 << DDC2)); // A1 & A2 OUTPUT PORTC |= ((1 << PORTC0) | (1 << PORTC2)); //A0 PULLUP, A2 HIGH } void loop() { readByte(); } byte readByte() { PINC |= B00000010; while(PINC & B00000001){     PINC &= B00000100; } PINC |= B00000100; byte b = (PINB << 2); b |= (PIND >> 6); PORTC ^= B00000010; // ack LOW delay(5); // hold ack LOW for a bit Serial.print((char)b); }