Commit 3348cbd4 authored by Mark van Renswoude's avatar Mark van Renswoude

Implemented getSensors

Changed to Adafruit PWM Servo library for PCA9685
Finalized PCB design for manufacturing
parent b635fce4
......@@ -5,4 +5,5 @@ bin
node_modules
src/secret.h
/kicad/Stairs.kicad_pcb-bak
/kicad/Stairs.bak
\ No newline at end of file
/kicad/Stairs.bak
kicad/output/*
\ No newline at end of file
This diff is collapsed.
(export (version D)
(design
(source P:\Electronics\Stairs\kicad\Stairs.sch)
(date "25-11-2018 19:41:52")
(date "25-11-2018 22:16:46")
(tool "Eeschema (5.0.1)-3")
(sheet (number 1) (name /) (tstamps /)
(title_block
......@@ -24,7 +24,7 @@
(tstamp 5B8AD5C2))
(comp (ref U2)
(value MAX485)
(footprint Housings_SOIC:SO-8_5.3x6.2mm_Pitch1.27mm)
(footprint MAX485-SO8:SO-8)
(datasheet "Maxim Integrated")
(fields
(field (name Field4) None)
......
......@@ -31,7 +31,7 @@ U 1 1 5B8AD72A
P 4700 6150
F 0 "U2" H 4700 6617 50 0000 C CNN
F 1 "MAX485" H 4700 6526 50 0000 C CNN
F 2 "Housings_SOIC:SO-8_5.3x6.2mm_Pitch1.27mm" H 4700 6150 60 0001 C CNN
F 2 "MAX485-SO8:SO-8" H 4700 6150 60 0001 C CNN
F 3 "Maxim Integrated" H 4700 6150 50 0001 L BNN
F 4 "None" H 4700 6150 50 0001 L BNN "Field4"
F 5 "Unavailable" H 4700 6150 50 0001 L BNN "Field5"
......
......@@ -2,4 +2,5 @@
(lib (name AMS1117-5.0)(type Legacy)(uri ${KIPRJMOD}/libs/AMS1117-5.0.mod)(options "")(descr ""))
(lib (name MAX485)(type Legacy)(uri ${KIPRJMOD}/libs/MAX485.mod)(options "")(descr ""))
(lib (name SMD-BUTTON_4P-5.2X5.2X1.5MM-SKQGAKE010_)(type Legacy)(uri ${KIPRJMOD}/libs/SMD-BUTTON_4P-5.2X5.2X1.5MM-SKQGAKE010_.mod)(options "")(descr ""))
(lib (name MAX485-SO8)(type KiCad)(uri ${KIPRJMOD}/libs/MAX485-SO8.pretty)(options "")(descr ""))
)
(module SO-8 (layer F.Cu) (tedit 5BFB111F)
(descr "8-Lead Plastic Small Outline, 5.3x6.2mm Body (http://www.ti.com.cn/cn/lit/ds/symlink/tl7705a.pdf)")
(tags "SOIC 1.27")
(attr smd)
(fp_text reference REF** (at 0 -4.13) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value SO-8 (at 0 4.13) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start -2.75 -2.55) (end -3.7 -2.55) (layer F.SilkS) (width 0.15))
(fp_line (start -2.75 3.205) (end 2.75 3.205) (layer F.SilkS) (width 0.15))
(fp_line (start -2.75 -3.205) (end 2.75 -3.205) (layer F.SilkS) (width 0.15))
(fp_line (start -2.75 3.205) (end -2.75 2.455) (layer F.SilkS) (width 0.15))
(fp_line (start 2.75 3.205) (end 2.75 2.455) (layer F.SilkS) (width 0.15))
(fp_line (start 2.75 -3.205) (end 2.75 -2.455) (layer F.SilkS) (width 0.15))
(fp_line (start -2.75 -3.205) (end -2.75 -2.55) (layer F.SilkS) (width 0.15))
(fp_line (start -3.9 3.35) (end 4.83 3.35) (layer F.CrtYd) (width 0.05))
(fp_line (start -3.9 -3.35) (end 3.9 -3.35) (layer F.CrtYd) (width 0.05))
(fp_line (start 3.9 -3.35) (end 3.9 3.35) (layer F.CrtYd) (width 0.05))
(fp_line (start -3.9 -3.35) (end -3.9 3.35) (layer F.CrtYd) (width 0.05))
(fp_line (start -2.65 -2.1) (end -1.65 -3.1) (layer F.Fab) (width 0.15))
(fp_line (start -2.65 3.1) (end -2.65 -2.1) (layer F.Fab) (width 0.15))
(fp_line (start 2.65 3.1) (end -2.65 3.1) (layer F.Fab) (width 0.15))
(fp_line (start 2.65 -3.1) (end 2.65 3.1) (layer F.Fab) (width 0.15))
(fp_line (start -1.65 -3.1) (end 2.65 -3.1) (layer F.Fab) (width 0.15))
(fp_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 8 smd rect (at 3.2 -1.905) (size 1 0.55) (layers F.Cu F.Paste F.Mask))
(pad 7 smd rect (at 3.2 -0.635) (size 1 0.55) (layers F.Cu F.Paste F.Mask))
(pad 6 smd rect (at 3.2 0.635) (size 1 0.55) (layers F.Cu F.Paste F.Mask))
(pad 5 smd rect (at 3.2 1.905) (size 1 0.55) (layers F.Cu F.Paste F.Mask))
(pad 4 smd rect (at -3.2 1.905) (size 1 0.55) (layers F.Cu F.Paste F.Mask))
(pad 3 smd rect (at -3.2 0.635) (size 1 0.55) (layers F.Cu F.Paste F.Mask))
(pad 2 smd rect (at -3.2 -0.635) (size 1 0.55) (layers F.Cu F.Paste F.Mask))
(pad 1 smd rect (at -3.2 -1.9) (size 1 0.55) (layers F.Cu F.Paste F.Mask))
(model ${KISYS3DMOD}/Housings_SOIC.3dshapes/SO-8_5.3x6.2mm_Pitch1.27mm.wrl
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
(module Housings_SOIC:SO-8_5.3x6.2mm_Pitch1.27mm (layer F.Cu) (tedit 59920130)
(descr "8-Lead Plastic Small Outline, 5.3x6.2mm Body (http://www.ti.com.cn/cn/lit/ds/symlink/tl7705a.pdf)")
(tags "SOIC 1.27")
(attr smd)
(fp_text reference REF** (at 0 -4.13) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value SO-8_5.3x6.2mm_Pitch1.27mm (at 0 4.13) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_line (start -2.75 -2.55) (end -4.5 -2.55) (layer F.SilkS) (width 0.15))
(fp_line (start -2.75 3.205) (end 2.75 3.205) (layer F.SilkS) (width 0.15))
(fp_line (start -2.75 -3.205) (end 2.75 -3.205) (layer F.SilkS) (width 0.15))
(fp_line (start -2.75 3.205) (end -2.75 2.455) (layer F.SilkS) (width 0.15))
(fp_line (start 2.75 3.205) (end 2.75 2.455) (layer F.SilkS) (width 0.15))
(fp_line (start 2.75 -3.205) (end 2.75 -2.455) (layer F.SilkS) (width 0.15))
(fp_line (start -2.75 -3.205) (end -2.75 -2.55) (layer F.SilkS) (width 0.15))
(fp_line (start -4.83 3.35) (end 4.83 3.35) (layer F.CrtYd) (width 0.05))
(fp_line (start -4.83 -3.35) (end 4.83 -3.35) (layer F.CrtYd) (width 0.05))
(fp_line (start 4.83 -3.35) (end 4.83 3.35) (layer F.CrtYd) (width 0.05))
(fp_line (start -4.83 -3.35) (end -4.83 3.35) (layer F.CrtYd) (width 0.05))
(fp_line (start -2.65 -2.1) (end -1.65 -3.1) (layer F.Fab) (width 0.15))
(fp_line (start -2.65 3.1) (end -2.65 -2.1) (layer F.Fab) (width 0.15))
(fp_line (start 2.65 3.1) (end -2.65 3.1) (layer F.Fab) (width 0.15))
(fp_line (start 2.65 -3.1) (end 2.65 3.1) (layer F.Fab) (width 0.15))
(fp_line (start -1.65 -3.1) (end 2.65 -3.1) (layer F.Fab) (width 0.15))
(fp_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(pad 8 smd rect (at 3.7 -1.905) (size 1.75 0.55) (layers F.Cu F.Paste F.Mask))
(pad 7 smd rect (at 3.7 -0.635) (size 1.75 0.55) (layers F.Cu F.Paste F.Mask))
(pad 6 smd rect (at 3.7 0.635) (size 1.75 0.55) (layers F.Cu F.Paste F.Mask))
(pad 5 smd rect (at 3.7 1.905) (size 1.75 0.55) (layers F.Cu F.Paste F.Mask))
(pad 4 smd rect (at -3.7 1.905) (size 1.75 0.55) (layers F.Cu F.Paste F.Mask))
(pad 3 smd rect (at -3.7 0.635) (size 1.75 0.55) (layers F.Cu F.Paste F.Mask))
(pad 2 smd rect (at -3.7 -0.635) (size 1.75 0.55) (layers F.Cu F.Paste F.Mask))
(pad 1 smd rect (at -3.7 -1.905) (size 1.75 0.55) (layers F.Cu F.Paste F.Mask))
(model ${KISYS3DMOD}/Housings_SOIC.3dshapes/SO-8_5.3x6.2mm_Pitch1.27mm.wrl
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
......@@ -113,6 +113,16 @@ void loop ()
void sendCommMessage(const byte* data, size_t len)
{
Serial.print("Raw out: ");
byte* ptr = data;
for (size_t i = 0; i < len; i++, ptr++)
{
Serial.print(*ptr, HEX);
Serial.print(' ');
}
Serial.println("");
digitalWrite(PinRS485WriteEnable, HIGH);
comm.sendMsg(data, len);
digitalWrite(PinRS485WriteEnable, LOW);
......@@ -188,12 +198,13 @@ void handlesetPWMCommand(SerialCommands* sender)
{
if (inLink) return;
int moduleIndex = atoi(sender->Next());
int flags = atoi(sender->Next());
int value1 = atoi(sender->Next());
int value2 = atoi(sender->Next());
sender->GetSerial()->println("> Ping");
const byte msg[] = { CommandSetPWM, (uint8_t)flags, (uint16_t)value1, (uint16_t)value2 };
sender->GetSerial()->println("> SetPWM");
const byte msg[] = { CommandSetPWM, moduleIndex, flags, lowByte(value1), highByte(value1), lowByte(value2), highByte(value2) };
sendCommMessage(msg, sizeof(msg));
}
......@@ -215,6 +226,15 @@ void handleCommMessage()
uint8_t* data = comm.getData();
uint8_t length = comm.getLength();
Serial.print("Raw in: ");
byte* ptr = data;
for (size_t i = 0; i < length; i++, ptr++)
{
Serial.print(*ptr, HEX);
Serial.print(' ');
}
Serial.println("");
if (length == 0)
return;
......@@ -239,16 +259,16 @@ void handleCommMessage()
case ResponseGetSensors:
Serial.println("< Get sensors response, module index = " + String(*data)); data++; length--;
if (length > 0)
if (length >= 2)
{
Serial.println(" Sensor 1 value: " + String(*data)); data++; length--;
Serial.println(" Sensor 1 value: " + String(*reinterpret_cast<uint16_t*>(data))); data+=2; length-=2;
}
else
Serial.println(" Sensor 1 value: <missing>");
if (length > 0)
if (length >= 2)
{
Serial.println(" Sensor 2 value: " + String(*data)); data++; length--;
Serial.println(" Sensor 2 value: " + String(*reinterpret_cast<uint16_t*>(data))); data+=2; length-=2;
}
else
Serial.println(" Sensor 2 value: <missing>");
......
......@@ -20,4 +20,5 @@ upload_speed = 115200
upload_protocol = usbtiny
lib_deps =
Adafruit GFX Library
\ No newline at end of file
Adafruit GFX Library
Adafruit PWM Servo Driver Library
\ No newline at end of file
......@@ -18,17 +18,30 @@ const uint32_t CommBaudRate = 76800;
// Arduino pin number connected to the MAX485's Receiver and Driver Output Enable pins
const uint8_t CommWriteEnablePin = 2;
// How long the display should stay on once it's idle and showing the
// current step numbers.
const uint32_t DisplayIdleTimeout = 5000;
// How long since the last packet before the communication icon shows
// as 'off'. Note that if a module is not configured for sensors and
// the light doesn't change either there will be no communication,
// so no need to panic immediately.
const uint32_t CommIdleTimeout = 1000;
// Arduino pin number connected to the push button.
// How long the display should stay on once it's idle and showing the
// current step numbers.
const uint32_t DisplayIdleTimeout = 5000;
// I2C address of the PCA9685 PWM driver
const uint8_t PWMDriverAddress = 0x40;
// Frequency of the PCA9685 PWM driver
const uint16_t PWMDriverFrequency = 1600;
// Arduino analog pin number connected to the sensors
const uint8_t PinSensor1 = 1;
const uint8_t PinSensor2 = 2;
// Arduino digital pin number connected to the push button.
const uint8_t PinButton = 8;
// Debounce time for the push button. Since it is not used for fast operations, this can be relatively high.
......
......@@ -23,6 +23,8 @@ void Display::init()
void Display::update()
{
// TODO invalidate when comm state changes
switch (state)
{
case State::WaitingForComm:
......
......@@ -5,6 +5,7 @@
* https://git.x2software.net/pub/Stairs
*/
#include "global.h"
#include "config.h"
int serialRead()
......@@ -26,6 +27,6 @@ size_t serialWrite(const byte what)
Settings settings;
Display display;
RS485 comm(serialRead, serialAvailable, serialWrite, 20);
PCA9685 pwmDriver;
Adafruit_PWMServoDriver pwmDriver(PWMDriverAddress);
State state = State::WaitingForComm;
uint32_t currentTime;
\ No newline at end of file
......@@ -8,7 +8,7 @@
#define __global
#include "lib/RS485_non_blocking.h"
#include "lib/PCA9685.h"
#include "Adafruit_PWMServoDriver.h"
#include "settings.h"
#include "display.h"
#include "state.h"
......@@ -16,7 +16,7 @@
extern Settings settings;
extern Display display;
extern RS485 comm;
extern PCA9685 pwmDriver;
extern Adafruit_PWMServoDriver pwmDriver;
extern State state;
extern uint32_t currentTime;
......
/*
* PCA9685 library for Arduino
* Copyright 2017 (c) Mark van Renswoude
*/
#include <stdint.h>
#include "./PCA9685.h"
#include <Wire.h>
#include <Arduino.h>
void PCA9685::setAddress(uint8_t address)
{
this->mAddress = address;
}
uint8_t PCA9685::read(uint8_t registerAddress)
{
uint8_t result = 0;
Wire.beginTransmission(this->mAddress);
Wire.write(registerAddress);
Wire.endTransmission();
Wire.requestFrom(this->mAddress, (uint8_t)1);
if (Wire.available())
result = Wire.read();
return result;
}
void PCA9685::write(uint8_t registerAddress, uint8_t value)
{
Wire.beginTransmission(this->mAddress);
Wire.write(registerAddress);
Wire.write(value);
Wire.endTransmission();
}
inline void PCA9685::write(uint8_t data)
{
Wire.write(data);
}
static const float prescaleValue = 25000000 / 4096;
void PCA9685::setPWMFrequency(float frequency)
{
// Credit to the Adafruit PWM Servo Driver library for these calculations
// https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library/
uint8_t prescale = floor(prescaleValue / (frequency * 0.9) - 0.5);
// Sleep while changing the frequency
uint8_t oldMode = this->read(PCA9685::RegisterMode1) & !PCA9685::Mode1Sleep;
uint8_t newMode = (oldMode & !PCA9685::Mode1Restart) | PCA9685::Mode1Sleep;
this->write(PCA9685::RegisterMode1, newMode);
this->write(PCA9685::RegisterPrescale, prescale);
this->write(PCA9685::RegisterMode1, oldMode);
// According to the datasheet:
// It takes 500 us max. for the oscillator to be up and running once
// SLEEP bit has been set to logic 0
//
// The Adafruit library uses 5 milliseconds, so I'll stick to that as well.
delay(5);
// Restart and turn on auto-increment (required for SetPWM)
this->write(PCA9685::RegisterMode1, oldMode | PCA9685::Mode1Restart | PCA9685::Mode1AI | PCA9685::Mode1AllCall);
}
void PCA9685::setPWM(uint8_t pin, uint16_t value)
{
if (value < 0) value = 0;
if (value > 4095) value = 4095;
if (value == 4095)
this->setPWM(pin, 4096, 0);
else if (value == 0)
this->setPWM(pin, 0, 4096);
else
this->setPWM(pin, 0, value);
}
void PCA9685::setPWM(uint8_t pin, uint16_t on, uint16_t off)
{
Wire.beginTransmission(this->mAddress);
this->write(PCA9685::RegisterLED0OnL + (4 * pin));
this->write(on);
this->write(on >> 8);
this->write(off);
this->write(off >> 8);
Wire.endTransmission();
}
void PCA9685::setAll(uint16_t value)
{
if (value < 0) value = 0;
if (value > 4095) value = 4095;
if (value == 4095)
this->setAll(4096, 0);
else if (value == 0)
this->setAll(0, 4096);
else
this->setAll(0, value);
}
void PCA9685::setAll(uint16_t on, uint16_t off)
{
Wire.beginTransmission(this->mAddress);
this->write(PCA9685::RegisterAllLEDOnL);
this->write(on);
this->write(on >> 8);
this->write(off);
this->write(off >> 8);
Wire.endTransmission();
}
\ No newline at end of file
/*
* PCA9685 library for Arduino
* Copyright 2017 (c) Mark van Renswoude
*/
#ifndef __PCA9685
#define __PCA9685
#include <stdint.h>
class PCA9685
{
private:
uint8_t mAddress;
protected:
uint8_t read(uint8_t registerAddress);
void write(uint8_t registerAddress, uint8_t value);
inline void write(uint8_t data);
public:
static const uint16_t Off = 0;
static const uint16_t On = 4095;
static const uint8_t RegisterMode1 = 0x0;
static const uint8_t RegisterPrescale = 0xFE;
static const uint8_t RegisterLED0OnL = 0x6;
static const uint8_t RegisterAllLEDOnL = 0xFA;
static const uint8_t Mode1Restart = 0x80;
static const uint8_t Mode1AI = 0x20;
static const uint8_t Mode1Sleep = 0x10;
static const uint8_t Mode1AllCall = 0x01;
// Call this if you already initialized the I2C library
void setAddress(uint8_t address);
void setPWMFrequency(float frequency);
void setPWM(uint8_t pin, uint16_t value);
void setPWM(uint8_t pin, uint16_t on, uint16_t off);
void setAll(uint16_t value);
void setAll(uint16_t on, uint16_t off);
};
#endif
\ No newline at end of file
......@@ -19,7 +19,9 @@ void setup()
// Set up I2C devices: the SSD1306 OLED display and PCA9685 LED PWM driver
Wire.begin();
display.init();
pwmDriver.setAddress(0x40);
pwmDriver.begin();
pwmDriver.setPWMFreq(PWMDriverFrequency);
// At 16 Mhz we pick a baud rate with a very acceptable 0.2% error rate
// Source: http://www.robotroom.com/Asynchronous-Serial-Communication-2.html
......@@ -47,9 +49,6 @@ void handleGetSensors(uint8_t* data, uint8_t length);
void checkButtonPress();
uint32_t test = 0;
int testState = LOW;
void loop()
{
currentTime = millis();
......@@ -59,13 +58,6 @@ void loop()
checkButtonPress();
display.update();
if (currentTime - test >= 500)
{
testState = testState == LOW ? HIGH : LOW;
test = currentTime;
digitalWrite(5, testState);
}
}
......@@ -187,18 +179,18 @@ void handleSetPWM(uint8_t* data, uint8_t length)
uint16_t value1 = *(reinterpret_cast<uint16_t*>(data)); data += 2;
uint16_t value2 = *(reinterpret_cast<uint16_t*>(data)); data += 2;
pwmDriver.setPWM(0, value1);
pwmDriver.setPWM(1, value2);
pwmDriver.setPin(0, value1);
pwmDriver.setPin(1, value2);
if (flags & SetPWMFlagModuleLEDs)
if ((flags & SetPWMFlagModuleLEDs) == SetPWMFlagModuleLEDs)
{
pwmDriver.setPWM(2, value1);
pwmDriver.setPWM(3, value2);
pwmDriver.setPin(2, value1);
pwmDriver.setPin(3, value2);
}
else
{
pwmDriver.setPWM(2, 0);
pwmDriver.setPWM(3, 0);
pwmDriver.setPin(2, 0);
pwmDriver.setPin(3, 0);
}
const uint8_t msg[] = { ResponseSetPWM, settings.getModuleIndex() };
......@@ -208,12 +200,10 @@ void handleSetPWM(uint8_t* data, uint8_t length)
void handleGetSensors(uint8_t* data, uint8_t length)
{
// TODO get sensor values
uint8_t sensor1 = 0;
uint8_t sensor2 = 0;
uint16_t value1 = analogRead(PinSensor1);
uint16_t value2 = analogRead(PinSensor2);
const uint8_t msg[] = { ResponseSetPWM, settings.getModuleIndex(), sensor1, sensor2 };
const uint8_t msg[] = { ResponseGetSensors, settings.getModuleIndex(), lowByte(value1), highByte(value1), lowByte(value2), highByte(value2) };
sendCommMessage(msg, sizeof(msg));
}
......
......@@ -145,8 +145,8 @@ const uint8_t SetPWMFlagModuleLEDs = 0x01;
* Response:
* [0] ResponseGetSensors
* [1] Module index
* [2] Analog (0-255) or digital (0, 255) value for sensor 1
* [3] Analog (0-255) or digital (0, 255) value for sensor 2
* [2,3] Analog (0-1023) or digital (0, 1023) value for sensor 1 (uint16_t)
* [4,5] Analog (0-1024) or digital (0, 1023) value for sensor 2 (uint16_t)
*/
const uint8_t BaseGetSensors = 0x30;
const uint8_t CommandGetSensors = BaseGetSensors | MaskModuleCommand;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment