From ca31fcc1ed28dfb46df0e2fa2cf3c3c66fb31fa8 Mon Sep 17 00:00:00 2001 From: mandlm Date: Sun, 7 Feb 2016 17:00:14 +0100 Subject: [PATCH] Simple HC-SR04 ultrasonic distance sensor setup --- UltraSonic/dist/KS0066.cpp | 225 +++++++++++++++++++++++++ UltraSonic/dist/KS0066.h | 55 ++++++ UltraSonic/dist/Pin.cpp | 43 +++++ UltraSonic/dist/Pin.h | 19 +++ UltraSonic/dist/ShiftRegister.cpp | 23 +++ UltraSonic/dist/ShiftRegister.h | 19 +++ UltraSonic/dist/dist.atsln | 22 +++ UltraSonic/dist/dist.componentinfo.xml | 86 ++++++++++ UltraSonic/dist/dist.cppproj | 137 +++++++++++++++ UltraSonic/dist/environment.h | 3 + UltraSonic/dist/main.cpp | 79 +++++++++ 11 files changed, 711 insertions(+) create mode 100644 UltraSonic/dist/KS0066.cpp create mode 100644 UltraSonic/dist/KS0066.h create mode 100644 UltraSonic/dist/Pin.cpp create mode 100644 UltraSonic/dist/Pin.h create mode 100644 UltraSonic/dist/ShiftRegister.cpp create mode 100644 UltraSonic/dist/ShiftRegister.h create mode 100644 UltraSonic/dist/dist.atsln create mode 100644 UltraSonic/dist/dist.componentinfo.xml create mode 100644 UltraSonic/dist/dist.cppproj create mode 100644 UltraSonic/dist/environment.h create mode 100644 UltraSonic/dist/main.cpp diff --git a/UltraSonic/dist/KS0066.cpp b/UltraSonic/dist/KS0066.cpp new file mode 100644 index 0000000..4291c45 --- /dev/null +++ b/UltraSonic/dist/KS0066.cpp @@ -0,0 +1,225 @@ +#include "KS0066.h" + +#include + +KS0066::KS0066() +{ + +} + +KS0066::KS0066(ShiftRegister &shiftRegister) +{ + setShiftRegister(shiftRegister); +} + +void KS0066::setShiftRegister(ShiftRegister &shiftRegister) +{ + m_shiftRegister = &shiftRegister; + + initDisplay(); +} + +void KS0066::initDisplay() +{ + _delay_ms(30); + + execute((1 << m_db5) | 1 << m_db4); + _delay_ms(5); + execute((1 << m_db5) | 1 << m_db4); + _delay_us(100); + execute((1 << m_db5) | 1 << m_db4); + execute((1 << m_db5)); + + functionSet(false, true, true); + + onOffControl(true, false, false); + displayClear(); + + entryMode(true, false); +} + +void KS0066::functionSet(bool interface8bit, bool twoLine, bool displayFont) +{ + uint8_t command = 0b00100000; + + if (interface8bit) + { + command |= (1 << 4); + } + + if (twoLine) + { + command |= (1 << 3); + } + + if (displayFont) + { + command |= (1 << 2); + } + + sendCommand(command); + + _delay_us(53); +} + +void KS0066::onOffControl(bool displayOn, bool cursorOn, bool blinkingOn) +{ + uint8_t command = 0b00001000; + + if (displayOn) + { + command |= (1 << 2); + } + + if (cursorOn) + { + command |= (1 << 1); + } + + if (blinkingOn) + { + command |= (1 << 0); + } + + sendCommand(command); + + _delay_us(53); +} + +void KS0066::displayClear() +{ + uint8_t command = 0b00000001; + + sendCommand(command); + + _delay_ms(2.16); +} + +void KS0066::entryMode(bool incrementMode, bool entireShift) +{ + uint8_t command = 0b00000100; + + if (incrementMode) + { + command |= (1 << 1); + } + + if (entireShift) + { + command |= (1 << 0); + } + + sendCommand(command); + + _delay_us(53); +} + +void KS0066::setCursorPos(uint8_t line, uint8_t column) +{ + sendCommand(0b10000000 + column + (line * 40)); +} + +void KS0066::sendCommand(uint8_t data) +{ + sendByte(data, true); +} + +void KS0066::sendChar(char c) +{ + sendByte(c, false); + + _delay_us(53); +} + +void KS0066::sendString(const char *string) +{ + uint8_t count = 0; + while (string != nullptr && *string != 0 && count < (m_lines * m_columns)) + { + if (count % m_columns == 0) + { + setCursorPos(count / m_columns, 0); + } + sendChar(*string); + string++; + count++; + } +} + +void KS0066::sendByte(uint8_t data, bool isCommand) +{ + uint8_t registerValue = 0; + + if (!isCommand) + { + registerValue |= (1 << m_rs); + } + + if (data & (1 << 7)) + { + registerValue |= (1 << m_db7); + } + + if (data & (1 << 6)) + { + registerValue |= (1 << m_db6); + } + + if (data & (1 << 5)) + { + registerValue |= (1 << m_db5); + } + + if (data & (1 << 4)) + { + registerValue |= (1 << m_db4); + } + + execute(registerValue); + + registerValue &= (1 << m_rs); + + if (data & (1 << 3)) + { + registerValue |= (1 << m_db7); + } + + if (data & (1 << 2)) + { + registerValue |= (1 << m_db6); + } + + if (data & (1 << 1)) + { + registerValue |= (1 << m_db5); + } + + if (data & (1 << 0)) + { + registerValue |= (1 << m_db4); + } + + execute(registerValue); +} + +void KS0066::execute(uint8_t registerValue) +{ + registerValue |= (1 << m_e); + m_shiftRegister->output(registerValue); + _delay_us(2); + + registerValue &= ~(1 << m_e); + m_shiftRegister->output(registerValue); +} + +void KS0066::set(const char *string) +{ + displayClear(); + sendString(string); +} + +void KS0066::clear() +{ + displayClear(); +} + diff --git a/UltraSonic/dist/KS0066.h b/UltraSonic/dist/KS0066.h new file mode 100644 index 0000000..87f98dc --- /dev/null +++ b/UltraSonic/dist/KS0066.h @@ -0,0 +1,55 @@ +#pragma once + +#include "environment.h" + +#include + +#include "ShiftRegister.h" + +class KS0066 +{ +private: + ShiftRegister *m_shiftRegister; + + static const uint8_t m_rs = 1; + static const uint8_t m_rw = 2; + static const uint8_t m_e = 3; + static const uint8_t m_db4 = 4; + static const uint8_t m_db5 = 5; + static const uint8_t m_db6 = 6; + static const uint8_t m_db7 = 7; + + uint8_t m_lines = 2; + uint8_t m_columns = 16; + +public: + KS0066(); + KS0066(ShiftRegister &shiftRegister); + + void setShiftRegister(ShiftRegister &shiftRegister); + + void clear(); + + void set(const char *string); + + +private: + + void initDisplay(); + + void functionSet(bool interface8bit, bool twoLine, bool displayOn); + void onOffControl(bool displayOn, bool cursorOn, bool blinkingOn); + void entryMode(bool incrementMode, bool entireShift); + void displayClear(); + + void setCursorPos(uint8_t line, uint8_t column); + + void sendCommand(uint8_t data); + + void sendChar(char c); + void sendString(const char *string); + + void sendByte(uint8_t data, bool isCommand); + + void execute(uint8_t registerValue); +}; \ No newline at end of file diff --git a/UltraSonic/dist/Pin.cpp b/UltraSonic/dist/Pin.cpp new file mode 100644 index 0000000..fed245b --- /dev/null +++ b/UltraSonic/dist/Pin.cpp @@ -0,0 +1,43 @@ +#include "Pin.h" + +#include "environment.h" + +#include + +Pin::Pin(volatile uint8_t *port, uint8_t pin) + : m_port(port) + , m_pin(pin) +{ + +} + +void Pin::pulse() +{ + *m_port |= (1 << m_pin); + *m_port &= ~(1 << m_pin); +} + +void Pin::set(bool value) +{ + if (value == true) + { + *m_port |= (1 << m_pin); + } + else + { + *m_port &= ~(1 << m_pin); + } +} + +void Pin::toggle() +{ + *m_port ^= (1 << m_pin); +} + +void Pin::blink() +{ + *m_port |= (1 << m_pin); + _delay_ms(50); + *m_port &= ~(1 << m_pin); +} + diff --git a/UltraSonic/dist/Pin.h b/UltraSonic/dist/Pin.h new file mode 100644 index 0000000..6b51006 --- /dev/null +++ b/UltraSonic/dist/Pin.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +class Pin +{ +private: + volatile uint8_t *m_port; + uint8_t m_pin; + +public: + Pin(volatile uint8_t *port, uint8_t pin); + + void pulse(); + void set(bool value); + void toggle(); + + void blink(); +}; diff --git a/UltraSonic/dist/ShiftRegister.cpp b/UltraSonic/dist/ShiftRegister.cpp new file mode 100644 index 0000000..75e22bf --- /dev/null +++ b/UltraSonic/dist/ShiftRegister.cpp @@ -0,0 +1,23 @@ +#include "ShiftRegister.h" + +ShiftRegister::ShiftRegister(volatile uint8_t *shiftClockPort, uint8_t shiftClockPin, + volatile uint8_t *dataPort, uint8_t dataPin, + volatile uint8_t *latchClockPort, uint8_t latchClockPin) + : m_shiftClockPin(shiftClockPort, shiftClockPin) + , m_dataPin(dataPort, dataPin) + , m_latchClockPin(latchClockPort, latchClockPin) +{ + +} + +void ShiftRegister::output(int8_t value) +{ + for (int8_t bitIdx = 7; bitIdx >= 0; --bitIdx) + { + m_dataPin.set(value & (1 << bitIdx)); + m_shiftClockPin.pulse(); + } + + m_latchClockPin.pulse(); +} + diff --git a/UltraSonic/dist/ShiftRegister.h b/UltraSonic/dist/ShiftRegister.h new file mode 100644 index 0000000..a2b2e4d --- /dev/null +++ b/UltraSonic/dist/ShiftRegister.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include "Pin.h" + +class ShiftRegister +{ + Pin m_shiftClockPin; + Pin m_dataPin; + Pin m_latchClockPin; + +public: + ShiftRegister(volatile uint8_t *shiftClockPort, uint8_t shiftClockPin, + volatile uint8_t *dataPort, uint8_t dataPin, + volatile uint8_t *latchClockPort, uint8_t latchClockPin); + + void output(int8_t value); +}; diff --git a/UltraSonic/dist/dist.atsln b/UltraSonic/dist/dist.atsln new file mode 100644 index 0000000..64b0e4f --- /dev/null +++ b/UltraSonic/dist/dist.atsln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Atmel Studio Solution File, Format Version 11.00 +VisualStudioVersion = 14.0.23107.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "dist", "dist.cppproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|AVR = Debug|AVR + Release|AVR = Release|AVR + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.ActiveCfg = Debug|AVR + {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|AVR.Build.0 = Debug|AVR + {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.ActiveCfg = Release|AVR + {DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.Build.0 = Release|AVR + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/UltraSonic/dist/dist.componentinfo.xml b/UltraSonic/dist/dist.componentinfo.xml new file mode 100644 index 0000000..23769e0 --- /dev/null +++ b/UltraSonic/dist/dist.componentinfo.xml @@ -0,0 +1,86 @@ + + + + + + + Device + Startup + + + Atmel + 1.0.0 + C:/Program Files (x86)\Atmel\Studio\7.0\Packs + + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.91\include + + include + C + + + include + + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.91\include\avr\iom32.h + + header + C + lmy51QeNKtBwSFwznyeJmw== + + include/avr/iom32.h + + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.91\templates\main.c + template + source + C Exe + GD1k8YYhulqRs6FD1B2Hog== + + templates/main.c + Main file (.c) + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.91\templates\main.cpp + template + source + C Exe + wKai3ogZ32ogXB2qogNlyQ== + + templates/main.cpp + Main file (.cpp) + + + + C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATmega_DFP\1.0.91\gcc\dev\atmega32 + + libraryPrefix + GCC + + + gcc/dev/atmega32 + + + + + ATmega_DFP + C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATmega_DFP/1.0.91/Atmel.ATmega_DFP.pdsc + 1.0.91 + true + ATmega32 + + + + Resolved + Fixed + true + + + \ No newline at end of file diff --git a/UltraSonic/dist/dist.cppproj b/UltraSonic/dist/dist.cppproj new file mode 100644 index 0000000..a6e812a --- /dev/null +++ b/UltraSonic/dist/dist.cppproj @@ -0,0 +1,137 @@ + + + + 2.0 + 7.0 + com.Atmel.AVRGCC8.CPP + dce6c7e3-ee26-4d79-826b-08594b9ad897 + ATmega32 + none + Executable + CPP + $(MSBuildProjectName) + .elf + $(MSBuildProjectDirectory)\$(Configuration) + dist + dist + dist + Native + true + false + true + true + 0x20000000 + + true + exception_table + 2 + 0 + com.atmel.avrdbg.tool.stk500 + + 0x1E9502 + + + + 125000 + + ISP + + com.atmel.avrdbg.tool.stk500 + + + STK500 + + ISP + 125000 + + + + + -mmcu=atmega32 -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.0.91\gcc\dev\atmega32" + True + True + True + True + False + True + True + %24(PackRepoDir)\atmel\ATmega_DFP\1.0.91\include + True + True + True + True + True + %24(PackRepoDir)\atmel\ATmega_DFP\1.0.91\include + True + True + True + -std=c++11 + libm + NDEBUG + Optimize for size (-Os) + NDEBUG + Optimize for size (-Os) + + + + + + + -mmcu=atmega32 -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.0.91\gcc\dev\atmega32" + True + True + True + True + False + True + True + %24(PackRepoDir)\atmel\ATmega_DFP\1.0.91\include + True + True + True + True + True + %24(PackRepoDir)\atmel\ATmega_DFP\1.0.91\include + True + True + True + -std=c++11 + libm + DEBUG + Optimize (-O1) + Default (-g2) + DEBUG + Optimize (-O1) + Default (-g2) + Default (-Wa,-g) + + + + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + compile + + + + \ No newline at end of file diff --git a/UltraSonic/dist/environment.h b/UltraSonic/dist/environment.h new file mode 100644 index 0000000..c05c7f5 --- /dev/null +++ b/UltraSonic/dist/environment.h @@ -0,0 +1,3 @@ +#pragma once + +#define F_CPU 12000000 \ No newline at end of file diff --git a/UltraSonic/dist/main.cpp b/UltraSonic/dist/main.cpp new file mode 100644 index 0000000..15f8c54 --- /dev/null +++ b/UltraSonic/dist/main.cpp @@ -0,0 +1,79 @@ +#include "environment.h" + +#include +#include + +#include + +#include "ShiftRegister.h" +#include "KS0066.h" + +int main(void) +{ + DDRC |= (1 << PC4) | (1 << PC3) | (1 << PC2); + + ShiftRegister shiftRegister(&PORTC, PC4, &PORTC, PC2, &PORTC, PC3); + KS0066 lcd(shiftRegister); + + lcd.set("Ultra-sonic"); + + DDRB |= (1 << PB0); // PB0 trigger output + DDRB &= ~(1 << PB1); // PB1 pulse input + + // Timer 1, normal mode + TCCR1A = 0; + + // Timer 1, clk/64 prescaler + TCCR1B |= (1 << CS10) | (1 << CS11); + + _delay_ms(2000); + lcd.clear(); + + while (true) + { + uint8_t errorNum = 0; + + PORTB |= (1 << PB0); + _delay_us(15); + PORTB &= ~(1 << PB0); + _delay_us(20); + + TCNT1 = 0; + while ((PINB & (1 << PB1)) == 0 && errorNum == 0) + { + if (TCNT1 > 60000) + { + errorNum = 1; + lcd.set("Timeout"); + } + } + + if (errorNum == 0) + { + TCNT1 = 0; + + while ((PINB & (1 << PB1)) != 0 && errorNum == 0) + { + if (TCNT1 > 60000) + { + errorNum = 2; + lcd.set("No object"); + } + } + + if (errorNum == 0) + { + uint16_t ticks = TCNT1; + + uint16_t cm = (ticks * 1.835) / 20.0; + + char buffer[16]; + sprintf(buffer, "%3i cm", cm); + lcd.set(buffer); + } + } + + _delay_ms(200); + } +} +