yannstatic/static/2020/08/04/Module-sans-fil-nRF24L01-et-interface-avec-Arduino.html

2198 lines
214 KiB
HTML
Raw Normal View History

2024-10-31 20:18:37 +01:00
<!DOCTYPE html><html lang="fr">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>Module sans fil nRF24L01+PA-LNA 2.4Ghz et interface avec Arduino - YannStatic</title>
<meta name="description" content="Module sans fil nRF24L01+PA-LNA">
<link rel="canonical" href="https://static.rnmkcy.eu/2020/08/04/Module-sans-fil-nRF24L01-et-interface-avec-Arduino.html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
<!-- - include head/favicon.html - -->
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
<!-- end custom head snippets --><script>(function() {
window.isArray = function(val) {
return Object.prototype.toString.call(val) === '[object Array]';
};
window.isString = function(val) {
return typeof val === 'string';
};
window.hasEvent = function(event) {
return 'on'.concat(event) in window.document;
};
window.isOverallScroller = function(node) {
return node === document.documentElement || node === document.body || node === window;
};
window.isFormElement = function(node) {
var tagName = node.tagName;
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
};
window.pageLoad = (function () {
var loaded = false, cbs = [];
window.addEventListener('load', function () {
var i;
loaded = true;
if (cbs.length > 0) {
for (i = 0; i < cbs.length; i++) {
cbs[i]();
}
}
});
return {
then: function(cb) {
cb && (loaded ? cb() : (cbs.push(cb)));
}
};
})();
})();
(function() {
window.throttle = function(func, wait) {
var args, result, thisArg, timeoutId, lastCalled = 0;
function trailingCall() {
lastCalled = new Date;
timeoutId = null;
result = func.apply(thisArg, args);
}
return function() {
var now = new Date,
remaining = wait - (now - lastCalled);
args = arguments;
thisArg = this;
if (remaining <= 0) {
clearTimeout(timeoutId);
timeoutId = null;
lastCalled = now;
result = func.apply(thisArg, args);
} else if (!timeoutId) {
timeoutId = setTimeout(trailingCall, remaining);
}
return result;
};
};
})();
(function() {
var Set = (function() {
var add = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (data[i] === item) {
return;
}
}
this.size ++;
data.push(item);
return data;
};
var Set = function(data) {
this.size = 0;
this._data = [];
var i;
if (data.length > 0) {
for (i = 0; i < data.length; i++) {
add.call(this, data[i]);
}
}
};
Set.prototype.add = add;
Set.prototype.get = function(index) { return this._data[index]; };
Set.prototype.has = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (this.get(i) === item) {
return true;
}
}
return false;
};
Set.prototype.is = function(map) {
if (map._data.length !== this._data.length) { return false; }
var i, j, flag, tData = this._data, mData = map._data;
for (i = 0; i < tData.length; i++) {
for (flag = false, j = 0; j < mData.length; j++) {
if (tData[i] === mData[j]) {
flag = true;
break;
}
}
if (!flag) { return false; }
}
return true;
};
Set.prototype.values = function() {
return this._data;
};
return Set;
})();
window.Lazyload = (function(doc) {
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
var createNode = function(name, attrs) {
var node = doc.createElement(name), attr;
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
node.setAttribute(attr, attrs[attr]);
}
}
return node;
};
var end = function(type, url) {
var s, q, qi, cbs, i, j, cur, val, flag;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
s[url] = true;
for (i = 0; i < q.length; i++) {
cur = q[i];
if (cur.urls.has(url)) {
qi = cur, val = qi.urls.values();
qi && (cbs = qi.callbacks);
for (flag = true, j = 0; j < val.length; j++) {
cur = val[j];
if (!s[cur]) {
flag = false;
}
}
if (flag && cbs && cbs.length > 0) {
for (j = 0; j < cbs.length; j++) {
cbs[j].call(context);
}
qi.load = true;
}
}
}
}
};
var load = function(type, urls, callback) {
var s, q, qi, node, i, cur,
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
for (i = 0; i < q.length; i++) {
cur = q[i];
if (_urls.is(cur.urls)) {
qi = cur;
break;
}
}
val = _urls.values();
if (qi) {
callback && (qi.load || qi.callbacks.push(callback));
callback && (qi.load && callback());
} else {
q.push({
urls: _urls,
callbacks: callback ? [callback] : [],
load: false
});
for (i = 0; i < val.length; i++) {
node = null, url = val[i];
if (s[url] === undefined) {
(type === 'js' ) && (node = createNode('script', { src: url }));
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
if (node) {
node.onload = (function(type, url) {
return function() {
end(type, url);
};
})(type, url);
(doc.head || doc.body).appendChild(node);
s[url] = false;
}
}
}
}
}
};
return {
js: function(url, callback) {
load('js', url, callback);
},
css: function(url, callback) {
load('css', url, callback);
}
};
})(this.document);
})();
</script><script>
(function() {
var TEXT_VARIABLES = {
version: '2.2.6',
sources: {
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
jquery: '/assets/js/jquery.min.js',
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
gitalk: {
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
},
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
},
site: {
toc: {
selectors: 'h1,h2,h3'
}
},
paths: {
search_js: '/assets/search.js'
}
};
window.TEXT_VARIABLES = TEXT_VARIABLES;
})();
</script>
</head>
<body>
<div class="root" data-is-touch="false">
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
<div class="header__title">
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
<!-- Champ de recherche -->
<div id="searchbox" class="search search--dark" style="visibility: visible">
<div class="main">
<div class="search__header"></div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<!-- <div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div> -->
</div>
</div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json',
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date}&nbsp;{title}</a></li>'
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
})
</script>
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/aide-jekyll-text-theme.html">Aide</a></li></ul>
</nav></div>
</header>
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">Module sans fil nRF24L01+PA-LNA 2.4Ghz et interface avec Arduino</h1></header></div><meta itemprop="headline" content="Module sans fil nRF24L01+PA-LNA 2.4Ghz et interface avec Arduino"><div class="article__info clearfix"><ul class="left-col menu"><li>
<a class="button button--secondary button--pill button--sm"
href="/archive.html?tag=arduino">arduino</a>
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">&nbsp;4&nbsp;août&nbsp;&nbsp;2020</span></li></ul></div><meta itemprop="datePublished" content="2020-08-04T00:00:00+02:00">
<meta itemprop="keywords" content="arduino"><div class="js-article-content">
<div class="layout--article"><!-- start custom article top snippet -->
<style>
#myBtn {
display: none;
position: fixed;
bottom: 10px;
right: 10px;
z-index: 99;
font-size: 12px;
font-weight: bold;
border: none;
outline: none;
background-color: white;
color: black;
cursor: pointer;
padding: 5px;
border-radius: 4px;
}
#myBtn:hover {
background-color: #555;
}
</style>
<button onclick="topFunction()" id="myBtn" title="Haut de page">&#8679;</button>
<script>
//Get the button
var mybutton = document.getElementById("myBtn");
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
mybutton.style.display = "block";
} else {
mybutton.style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>
<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><details>
<summary><b>Afficher/cacher Sommaire</b></summary>
<!-- affichage sommaire -->
<div class="toc-aside js-toc-root"></div>
</details><h1 id="module-sans-fil-nrf24l01pa-lna">Module sans fil nRF24L01+PA-LNA</h1>
<p><img src="/images/nRF24L01-PA-LNA.png" alt="nRF24L01+PA-LNA" /></p>
<p>Le fait que deux cartes Arduino ou plus puissent communiquer entre elles sans fil à distance ouvre de nombreuses possibilités, telles que la surveillance à distance des données de capteurs, le contrôle des robots, la domotique, etc. Et lorsquil sagit de solutions RF bidirectionnelles fiables et peu coûteuses, personne ne fait mieux que le module émetteur-récepteur nRF24L01 + de <a href="http://www.nordicsemi.com/">Nordic Semiconductor</a></p>
<h2 id="vue-densemble-du-matériel">Vue densemble du matériel</h2>
<h3 id="fréquence-radio">Fréquence radio</h3>
<p>Le module démetteur-récepteur nRF24L01 + est conçu pour fonctionner dans la bande de fréquence ISM mondiale de 2,4 GHz et utilise la modulation GFSK pour la transmission de données. Le taux de transfert de données peut être lun des 250 kbps, 1 Mbit/s et 2 Mbit/s.</p>
<blockquote>
<p><strong>Quelle est la bande 2,4 GHz ISM?</strong><br />
La bande de 2,4 GHz est lune des bandes industrielle, scientifique et médicale (ISM) réservées au niveau international pour lutilisation dappareils de faible puissance sans licence. Les exemples sont les téléphones sans fil, les périphériques Bluetooth, les périphériques de communication en champ proche (NFC) et les réseaux informatiques sans fil (WiFi) utilisent tous les fréquences ISM.</p>
</blockquote>
<h3 id="consommation-dénergie">Consommation dénergie</h3>
<p>La tension de fonctionnement du module est comprise entre <strong>1,9 et 3,6 V</strong> , mais la bonne nouvelle est que les <u>broches logiques sont tolérantes à 5 V</u> , ce qui permet de le connecter facilement à un microcontrôleur Arduino ou à tout autre microprocesseur logique sans utiliser de convertisseur de niveau logique.</p>
<p>Le module prend en charge la puissance de sortie programmable, à savoir. 0 dBm, -6 dBm, -12 dBm ou -18 dBm et consomme incroyablement environ <strong>12 mA pendant la transmission à 0 dBm</strong>, ce qui est même inférieur à une seule LED. Et surtout, il consomme 26 µA en mode veille et 900 nA en mode veille. Cest pourquoi ils sont le périphérique sans fil de prédilection pour les applications à faible consommation.</p>
<h3 id="interface-spi">Interface SPI</h3>
<p>Le module émetteur-récepteur nRF24L01 + communique via une interface <strong>SPI</strong> (Serial Peripheral Interface) à 4 broches avec un débit binaire maximal de 10 Mbps . Tous les paramètres tels que le canal de fréquence (125 canaux sélectionnables), la puissance de sortie (0 dBm, -6 dBm, -12 dBm ou -18 dBm) et le débit de données (250kbps, 1Mbps ou 2Mbps) peuvent être configurés via linterface SPI.</p>
<p>Le bus SPI utilise le concept de maître et desclave. Dans la plupart des applications, notre Arduino est le maître et le module émetteur-récepteur nRF24L01 + est lesclave. Contrairement au bus I2C, le nombre desclaves sur le bus SPI est limité. Sur l<u>Arduino Uno, vous pouvez utiliser un maximum de deux esclaves SPI</u>, cest-à-dire deux modules émetteur-récepteur nRF24L01 +.</p>
<p>Spécification du module démetteur-récepteur nRF24L01 + :</p>
<table>
<thead>
<tr>
<th>nRF24L01 +</th>
<th>spécification</th>
</tr>
</thead>
<tbody>
<tr>
<td>Gamme de fréquences</td>
<td>Bande ISM de 2,4 GHz</td>
</tr>
<tr>
<td>Débit de données aérien maximal</td>
<td>2 Mb/s</td>
</tr>
<tr>
<td>Format de modulation</td>
<td>GFSK</td>
</tr>
<tr>
<td>Max. Puissance de sortie</td>
<td>0 dBm</td>
</tr>
<tr>
<td>Tension dalimentation de fonctionnement</td>
<td>1,9 V à 3,6 V</td>
</tr>
<tr>
<td>Max. Courant de fonctionnement</td>
<td>13,5mA</td>
</tr>
<tr>
<td>Min. Courant (mode veille)</td>
<td>26µA</td>
</tr>
<tr>
<td>Entrées logiques</td>
<td>5V tolérant</td>
</tr>
<tr>
<td>Gamme de communication</td>
<td>800+ m (ligne de mire)</td>
</tr>
</tbody>
</table>
<p>Pour plus dinformations sur le nRF24L01 + IC, consultez la <a href="/files/nrf24L01+2.4ghz-transceiver-datasheet.pdf">fiche technique (pdf)</a></p>
<h3 id="nrf24l01-module-vs-nrf24l01-palna-module">nRF24L01+ module Vs nRF24L01+ PA/LNA module</h3>
<p>Il existe toute une gamme de modules basés sur la puce nRF24L01 +. Voici les versions les plus populaires.</p>
<p><img src="/images/nRF24L01-Wireless-Transceiver-Module.png" alt="" /><br />
<em>Module sans fil nRF24L01 +</em> <br />
La première version utilise une antenne intégrée. Cela permet une version plus compacte de lévasion. Cependant, la petite antenne signifie également une plage de transmission inférieure. Avec cette version, vous pourrez communiquer sur une distance de 100 mètres . Bien sûr, cest à lextérieur dans un espace ouvert. Votre portée à lintérieur, surtout à travers les murs, sera légèrement affaiblie.</p>
<p><img src="/images/nRF24L01-PA-LNA-External-Antenna-Wireless-Transceiver-Module.png" alt="" /><br />
<em>Module démetteur-récepteur sans fil LNA nRF24L01 + PA avec antenne externe</em><br />
La deuxième version est livrée avec un connecteur SMA et une antenne canard, mais ce nest pas la vraie différence. La vraie différence est quil est livré avec une puce spéciale RFX2401C qui intègre les circuits de commutation PA, LNA et émission-réception. Cette puce dextension de portée, associée à une antenne de canard, aide le module à atteindre une portée de transmission considérablement plus grande, de lordre de 1000 m.</p>
<h3 id="quest-ce-que-pa-lna">Quest-ce que PA LNA?</h3>
<p>Le PA signifie amplificateur de puissance . Il augmente simplement la puissance du signal transmis par la puce nRF24L01 +. Tandis que LNA signifie <strong>amplificateur à faible bruit</strong> . La fonction de la LNA est de prendre le signal extrêmement faible et incertain de lantenne (généralement de lordre des microvolts ou inférieur à -100 dBm) et lamplifier à un niveau plus utile (généralement entre 0,5 et 1V)</p>
<p><img src="/images/nRF24L01-RF-PA-LNA-Power-Amplifier-Low-Noise-Amplifier-Block-Diagram.png" alt="" /></p>
<p>Lamplificateur à faible bruit (LNA) du trajet de réception et lamplificateur de puissance (PA) du trajet de transmission se connectent à lantenne via un duplexeur, ce qui sépare les deux signaux et empêche la sortie relativement puissante du PA de surcharger lentrée sensible du LNA. Pour plus dinformations, consultez cet <a href="https://www.digikey.com/en/articles/techzone/2013/oct/understanding-the-basics-of-low-noise-and-power-amplifiers-in-wireless-designs">article sur digikey.com</a></p>
<h2 id="comment-fonctionne-le-module-émetteur-récepteur-nrf24l01-">Comment fonctionne le module émetteur-récepteur nRF24L01 +?</h2>
<h3 id="fréquence-du-canal-rf">Fréquence du canal RF</h3>
<p>Le module émetteur-récepteur nRF24L01 + transmet et reçoit des données sur une certaine fréquence appelée canal . De plus, pour que deux ou plusieurs modules démetteur-récepteur puissent communiquer lun avec lautre, ils doivent se trouver sur le même canal. Ce canal peut être nimporte quelle fréquence dans la bande ISM à 2,4 GHz ou, plus précisément, entre 2 200 et 2 525 GHz (2 400 à 2 525 MHz).</p>
<p>Chaque canal occupe une largeur de bande inférieure à 1 MHz. Cela nous donne 125 canaux possibles avec un espacement de 1 MHz. Ainsi, le module peut utiliser 125 canaux différents, ce qui permet davoir un réseau de 125 modems fonctionnant de manière indépendante à un endroit. <br />
<img src="/images/nRF24L01-Wireless-Transceiver-2.4GHz-125-RF-Channels-1MHz-Spacing.png" alt="" /></p>
<blockquote>
<p>**REMARQUE : ** Le canal occupe une bande passante inférieure à 1 MHz à 250 kbps et à un débit binaire de 1 Mbps. Toutefois, à un débit binaire de 2 Mbits / s, une largeur de bande de 2 MHz est occupée (plus large que la résolution du paramètre de fréquence du canal RF). Ainsi, pour garantir des canaux ne se chevauchant pas et réduire la diaphonie en mode 2 Mbps, <u>vous devez conserver un espacement de 2 MHz entre deux canaux</u>.</p>
</blockquote>
<p>La fréquence de canal RF du canal sélectionné est définie selon la formule suivante:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Freq(sélectionné) = 2400 + CH(sélectionné)
</code></pre></div></div>
<p>Par exemple, si vous sélectionnez 108 comme canal pour la transmission de données, la fréquence du canal RF de votre canal sera de 2508 MHz → (2400 + 108).</p>
<h3 id="nrf24l01--réseau-multicouche">nRF24L01 + réseau multicouche</h3>
<p>Le nRF24L01 + fournit une fonctionnalité appelée Multiceiver . Cest une abréviation pour plusieurs émetteurs, récepteur unique. Chaque canal RF est divisé logiquement en 6 canaux de données parallèles appelés canaux de données . En dautres termes, un canal de données est un canal logique dans le canal RF physique. Chaque canal de données a sa propre adresse physique (adresse de canal de données) et peut être configuré. Ceci peut être illustré comme indiqué ci-dessous. <br />
<img src="/images/nRF24L01-Wireless-Multiceiver-Network-Multiple-Transmitters-Single-Receiver.png" alt="" /><br />
Pour simplifier le diagramme ci-dessus, imaginez le récepteur principal agissant en tant que récepteur concentrateur collectant simultanément des informations de 6 nœuds démetteurs différents. Le récepteur pivot peut cesser découter à tout moment et fait office démetteur. Mais cela ne peut être fait quun tuyau/noeud (pipe/node) à la fois.</p>
<h3 id="protocole-shockburst-amélioré">Protocole ShockBurst amélioré</h3>
<p>Le module émetteur-récepteur nRF24L01 + utilise une structure de paquets appelée Enhanced ShockBurst. Cette structure de paquet simple est décomposée en 5 champs différents, illustrés ci-dessous.<br />
<img src="/images/nRF24L01-Wireless-Transceiver-Enhanced-ShockBurst-Packet-Structure.png" alt="" /><br />
La structure dorigine de ShockBurst ne comprenait que les champs Préambule, Adresse, Charge utile et Contrôle de redondance cyclique (CRC). ShockBurst amélioré a apporté une fonctionnalité accrue pour des communications améliorées utilisant un champ de commande de paquets (PCF) récemment introduit.</p>
<p>Cette nouvelle structure est excellente pour plusieurs raisons. Premièrement, il autorise les charges utiles de longueur variable avec un spécificateur de longueur de charge utile, ce qui signifie que les charges utiles peuvent varier de 1 à 32 octets.</p>
<p>Deuxièmement, il attribue à chaque paquet envoyé un identifiant de paquet, ce qui permet au périphérique récepteur de déterminer si un message est nouveau ou sil a été retransmis (et peut donc être ignoré).</p>
<p>Enfin et surtout, chaque message peut demander lenvoi dun accusé de réception lorsquil est reçu par un autre appareil.</p>
<h3 id="nrf24l01--traitement-automatique-des-paquets">nRF24L01 + Traitement automatique des paquets</h3>
<p>Passons maintenant à trois scénarios pour mieux comprendre la façon dont deux modules nRF24L01 + se traitent.</p>
<p><strong>Transaction avec accusé de réception et interruption</strong>
Ceci est un exemple de scénario positif. Ici, lémetteur commence une communication en envoyant un paquet de données au récepteur. Une fois que tout le paquet est transmis, il attend (environ 130 µs) la réception du paquet daccusé de réception (paquet ACK). Lorsque le destinataire reçoit le paquet, il envoie un paquet ACK à lémetteur. À la réception du paquet ACK, lémetteur émet un signal dinterruption (IRQ) pour indiquer que les nouvelles données sont disponibles.<br />
<img src="/images/nRF24L01-Transceiver-Working-Packet-Transmission.gif" alt="" /></p>
<p><strong>Transaction avec perte de paquet de données</strong><br />
Il sagit dun scénario négatif dans lequel une retransmission est nécessaire en raison de la perte du paquet transmis. Une fois le paquet transmis, lémetteur attend la réception du paquet ACK. Si lémetteur ne lobtient pas dans le délai ARD (Auto-Retransmit-Delay), le paquet est retransmis. Lorsque le paquet retransmis est reçu par le récepteur, le paquet ACK est transmis, ce qui génère à son tour une interruption au niveau de lémetteur.<br />
<img src="/images/nRF24L01-Transceiver-Working-Packet-Transmission-Data-Lost.gif" alt="" /></p>
<p><strong>Transaction avec accusé de réception perdu</strong><br />
Il sagit à nouveau dun scénario négatif dans lequel une retransmission est nécessaire en raison de la perte du paquet ACK. Ici, même si le destinataire reçoit le paquet lors de la première tentative, en raison de la perte du paquet ACK, lémetteur pense que le destinataire na pas du tout reçu le paquet. Ainsi, une fois le délai de retransmission automatique écoulé, il retransmet le paquet. Désormais, lorsque le destinataire reçoit le paquet contenant le même identifiant de paquet que précédemment, il le rejette et envoie à nouveau le paquet ACK.<br />
<img src="/images/nRF24L01-Transceiver-Working-Packet-Transmission-Acknowledgement-Lost.gif" alt="" /></p>
<h2 id="brochage-du-module-démetteur-récepteur-nrf24l01-">Brochage du module démetteur-récepteur nRF24L01 +</h2>
<p>Examinons le brochage des deux versions du module émetteur-récepteur nRF24L01 +. <br />
<img src="/images/Pinout-nRF24L01-Wireless-Transceiver-Module.png" alt="" /><br />
<img src="/images/Pinout-nRF24L01-PA-LNA-External-Antenna-Wireless-Transceiver-Module.png" alt="" /></p>
<ul>
<li><strong><em>GND</em></strong> est la broche de terre. Il est généralement marqué en entourant la broche dans un carré afin de pouvoir être utilisé comme référence pour identifier les autres broches.</li>
<li><strong><em>VCC</em></strong> alimente le module. Cela peut être nimporte où de 1,9 à 3,9 volts. Vous pouvez le connecter à la sortie 3.3V de votre Arduino. Noubliez pas que le connecter à une broche 5V détruira probablement votre module nRF24L01 +!</li>
<li><strong><em>CE</em></strong> (Chip Enable) est une broche active-HIGH. Lorsque sélectionné, le nRF24L01 transmettra ou recevra, selon le mode dans lequel il se trouve actuellement.</li>
<li><strong><em>CSN</em></strong> (Chip Select Not) est une broche active-LOW et est normalement maintenue à létat HIGH. Lorsque cette broche devient faible, le nRF24L01 commence à écouter les données sur son port SPI et les traite en conséquence.</li>
<li><strong><em>SCK</em></strong> (Serial Clock) accepte les impulsions dhorloge fournies par le maître du bus SPI.</li>
<li><strong><em>MOSI</em></strong> (Master Out Slave In) est lentrée SPI du nRF24L01.</li>
<li><strong><em>MISO</em></strong> (Master In Slave Out) est la sortie SPI du nRF24L01.</li>
<li><strong><em>IRQ</em></strong> est une broche dinterruption pouvant alerter le maître lorsque de nouvelles données sont disponibles pour traitement.</li>
</ul>
<h2 id="arduino--émetteur-récepteur-nrf24l01">Arduino + émetteur-récepteur nRF24L01+</h2>
<h3 id="câblage---connexion-du-module-émetteur-récepteur-nrf24l01-à-un-arduino-uno">Câblage - Connexion du module émetteur-récepteur nRF24L01+ à un Arduino UNO</h3>
<p>Maintenant que nous comprenons parfaitement le fonctionnement du module émetteur-récepteur nRF24L01 +, nous pouvons commencer à le connecter à notre Arduino!</p>
<p>Pour commencer, connectez la broche VCC du module à 3,3 V sur lArduino et la broche GND à la terre. Les broches CSN et CE peuvent être connectées à nimporte quelle broche numérique de lArduino. Dans notre cas, il est connecté aux broches numériques n ° 8 et n ° 9 respectivement. Nous en sommes maintenant aux broches utilisées pour la communication SPI.</p>
<p>Le module émetteur-récepteur nRF24L01 + nécessitant beaucoup de transfert de données, il offrira les meilleures performances lorsquil est connecté aux broches SPI matérielles dun microcontrôleur. Les broches SPI matérielles sont beaucoup plus rapides que le “bit-bang” du code dinterface à laide dun autre ensemble de broches.</p>
<p>Notez que chaque carte Arduino a différentes broches SPI qui doivent être connectées en conséquence. Pour les cartes Arduino telles que UNO / Nano V3.0, ces broches sont numériques 13 (SCK), 12 (MISO) et 11 (MOSI).</p>
<p>Si vous avez un Mega, les pins sont différents! Vous voudrez utiliser les technologies numériques 50 (MISO), 51 (MOSI), 52 (SCK) et 53 (SS).<br />
Config. Broches SPI dArduino Uno, Arduino Nano et Arduino Mega</p>
<table>
<thead>
<tr>
<th>_</th>
<th>MOSI</th>
<th>MISO</th>
<th>SCK</th>
<th>SS</th>
</tr>
</thead>
<tbody>
<tr>
<td>Arduino Uno</td>
<td>11</td>
<td>12</td>
<td>13</td>
<td>10</td>
</tr>
<tr>
<td>Arduino Nano</td>
<td>11</td>
<td>12</td>
<td>13</td>
<td>10</td>
</tr>
<tr>
<td>Arduino Mega</td>
<td>51</td>
<td>50</td>
<td>52</td>
<td>53</td>
</tr>
</tbody>
</table>
<p>Si vous utilisez une carte Arduino différente de celle mentionnée ci-dessus, il est conseillé de vérifier la <a href="https://www.arduino.cc/en/Reference/SPI">documentation officielle</a> dArduino avant de poursuivre.</p>
<p><img src="/images/Arduino-Wiring-Fritzing-Connections-with-nRF24L01-Wireless-Transceiver-Module.png" alt="" /><br />
<em>Câblage du module émetteur-récepteur sans fil nRF24L01 + sur Arduino UNO</em></p>
<p><img src="/images/Arduino-Wiring-Fritzing-Connections-with-nRF24L01-PA-LNA-External-Antenna-Wireless-Module.png" alt="" /><br />
<em>Câblage du module sans fil nRF24L01 + PA LNA à Arduino UNO</em></p>
<blockquote>
<p>Vous devez faire deux de ces circuits. Lun agit comme émetteur et lautre comme récepteur. Le câblage pour les deux est identique.</p>
</blockquote>
<h3 id="rf24-bibliothèque-arduino-pour-nrf24l01--module">RF24 Bibliothèque Arduino pour nRF24L01 + Module</h3>
<p>Linterfaçage avec le module émetteur-récepteur nRF24L01 + est un travail fastidieux, mais heureusement pour nous, de nombreuses bibliothèques sont disponibles. <a href="http://tmrh20.github.io/RF24/">RF24</a> est lune des bibliothèques les plus populaires. Cette bibliothèque existe depuis plusieurs années. Il est simple à utiliser pour les débutants, mais offre encore beaucoup pour les utilisateurs avancés. Dans nos expériences, nous utiliserons la même bibliothèque.</p>
<p>Vous pouvez télécharger la dernière version de la bibliothèque sur le <a href="https://github.com/nRF24/RF24">fork du référentiel RF24 GitHub</a> ou <a href="https://lastminuteengineers.com/libraries/RF24-master.zip">télécharger le zip</a></p>
<p>Pour linstaller, ouvrez lEDI Arduino, accédez à Esquisse&gt; Inclure la bibliothèque&gt; Ajouter une bibliothèque .ZIP, puis sélectionnez le fichier maître RF24 que vous venez de télécharger. Si vous avez besoin de plus de détails sur linstallation dune bibliothèque, consultez ce <a href="https://www.arduino.cc/en/Guide/Libraries">tutoriel sur linstallation dune bibliothèque Arduino</a>.</p>
<h3 id="code-arduino---pour-émetteur">Code Arduino - pour émetteur</h3>
<p>Dans notre expérience, nous allons simplement envoyer un message traditionnel “ Hello World “ de lémetteur au récepteur.</p>
<p>Voici le schéma que nous allons utiliser pour notre émetteur:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//Include Libraries</span>
<span class="cp">#include</span> <span class="cpf">&lt;SPI.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;nRF24L01.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;RF24.h&gt;</span><span class="cp">
</span>
<span class="c1">//create an RF24 object</span>
<span class="n">RF24</span> <span class="nf">radio</span><span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span> <span class="c1">// CE, CSN</span>
<span class="c1">//address through which two modules communicate.</span>
<span class="k">const</span> <span class="n">byte</span> <span class="n">address</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="s">"00001"</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span>
<span class="p">{</span>
<span class="n">radio</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
<span class="c1">//set the address</span>
<span class="n">radio</span><span class="p">.</span><span class="n">openWritingPipe</span><span class="p">(</span><span class="n">address</span><span class="p">);</span>
<span class="c1">//Set module as transmitter</span>
<span class="n">radio</span><span class="p">.</span><span class="n">stopListening</span><span class="p">();</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">//Send message to receiver</span>
<span class="k">const</span> <span class="kt">char</span> <span class="n">text</span><span class="p">[]</span> <span class="o">=</span> <span class="s">"Hello World"</span><span class="p">;</span>
<span class="n">radio</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="o">&amp;</span><span class="n">text</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">text</span><span class="p">));</span>
<span class="n">delay</span><span class="p">(</span><span class="mi">1000</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Lesquisse commence par inclure les bibliothèques. La bibliothèque SPI.h gère la communication SPI tandis que nRF24L01.h et RF24.h contrôlent le module.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//Include Libraries</span>
<span class="cp">#include</span> <span class="cpf">&lt;SPI.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;nRF24L01.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;RF24.h&gt;</span><span class="cp">
</span></code></pre></div></div>
<p>Ensuite, nous devons créer un objet RF24. Lobjet prend deux numéros de broches en tant que paramètres auxquels les signaux CE et CSN sont connectés.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//create an RF24 object</span>
<span class="n">RF24</span> <span class="nf">radio</span><span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span> <span class="c1">// CE, CSN</span>
</code></pre></div></div>
<p>Ensuite, nous devons créer un tableau doctets qui représentera ladresse du canal par lequel deux modules nRF24L01 + communiquent.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//address through which two modules communicate.</span>
<span class="k">const</span> <span class="n">byte</span> <span class="n">address</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="s">"00001"</span><span class="p">;</span>
</code></pre></div></div>
<p>Nous pouvons modifier la valeur de cette adresse pour nimporte quelle chaîne de 5 lettres telle que «node1». Ladresse est nécessaire si vous avez quelques modules dans un réseau. Grâce à ladresse, vous pouvez choisir un module particulier avec lequel vous souhaitez communiquer, de sorte que dans notre cas, nous aurons la même adresse pour lémetteur et le récepteur.</p>
<p>Ensuite, dans la fonction de configuration: nous devons initialiser lobjet radio à laide de <code class="language-plaintext highlighter-rouge">radio.begin()</code> et en utilisant la fonction <code class="language-plaintext highlighter-rouge">radio.openWritingPipe()</code> , nous définissons ladresse de lémetteur.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//set the address</span>
<span class="n">radio</span><span class="p">.</span><span class="n">openWritingPipe</span><span class="p">(</span><span class="n">address</span><span class="p">);</span>
</code></pre></div></div>
<p>Enfin, nous utiliserons la fonction <code class="language-plaintext highlighter-rouge">radio.stopListening()</code> qui définit le module comme émetteur.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//Set module as transmitter</span>
<span class="n">radio</span><span class="p">.</span><span class="n">stopListening</span><span class="p">();</span>
</code></pre></div></div>
<p>Dans la section de la boucle: nous créons un tableau de caractères auquel nous affectons le message «Hello World». En utilisant la fonction <code class="language-plaintext highlighter-rouge">radio.write()</code> , nous enverrons ce message au destinataire. Le premier argument ici est le message que nous voulons envoyer. Le deuxième argument est le nombre doctets présents dans ce message.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">const</span> <span class="kt">char</span> <span class="n">text</span><span class="p">[]</span> <span class="o">=</span> <span class="s">"Hello World"</span><span class="p">;</span>
<span class="n">radio</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="o">&amp;</span><span class="n">text</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">text</span><span class="p">));</span>
</code></pre></div></div>
<p>Grâce à cette méthode, vous pouvez envoyer jusquà 32 octets à la fois. Parce que cest la taille maximale dun seul paquet que nRF24L01 + peut gérer. Si vous avez besoin dune confirmation que le destinataire a reçu des données, la méthode <code class="language-plaintext highlighter-rouge">radio.write()</code> renvoie une valeur <code class="language-plaintext highlighter-rouge">bool</code> . Sil renvoie TRUE, les données sont parvenues au destinataire. Sil renvoie FALSE, les données ont été perdues.</p>
<blockquote>
<p><strong>REMARQUE :</strong> la fonction <code class="language-plaintext highlighter-rouge">radio.write()</code> bloque le programme jusquà ce quil reçoive laccusé de réception ou quil ny ait plus aucune tentative de retransmission.</p>
</blockquote>
<h3 id="code-arduino---pour-le-récepteur">Code Arduino - Pour le récepteur</h3>
<p>Voici le croquis que nous allons utiliser pour notre récepteur</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//Include Libraries</span>
<span class="cp">#include</span> <span class="cpf">&lt;SPI.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;nRF24L01.h&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;RF24.h&gt;</span><span class="cp">
</span>
<span class="c1">//create an RF24 object</span>
<span class="n">RF24</span> <span class="nf">radio</span><span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span> <span class="c1">// CE, CSN</span>
<span class="c1">//address through which two modules communicate.</span>
<span class="k">const</span> <span class="n">byte</span> <span class="n">address</span><span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=</span> <span class="s">"00001"</span><span class="p">;</span>
<span class="kt">void</span> <span class="nf">setup</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">Serial</span><span class="p">);</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">begin</span><span class="p">(</span><span class="mi">9600</span><span class="p">);</span>
<span class="n">radio</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span>
<span class="c1">//set the address</span>
<span class="n">radio</span><span class="p">.</span><span class="n">openReadingPipe</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">address</span><span class="p">);</span>
<span class="c1">//Set module as receiver</span>
<span class="n">radio</span><span class="p">.</span><span class="n">startListening</span><span class="p">();</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">loop</span><span class="p">()</span>
<span class="p">{</span>
<span class="c1">//Read the data if available in buffer</span>
<span class="k">if</span> <span class="p">(</span><span class="n">radio</span><span class="p">.</span><span class="n">available</span><span class="p">())</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="n">text</span><span class="p">[</span><span class="mi">32</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="n">radio</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="o">&amp;</span><span class="n">text</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">text</span><span class="p">));</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Ce programme ressemble beaucoup au programme de lémetteur, à lexception de quelques modifications.</p>
<p>Au début de la fonction de configuration, nous commençons la communication série. Ensuite, en utilisant la fonction <code class="language-plaintext highlighter-rouge">radio.setReadingPipe()</code> , nous définissons la même adresse que celle de lémetteur, ce qui permet la communication entre lémetteur et le récepteur.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="c1">//set the address</span>
<span class="n">radio</span><span class="p">.</span><span class="n">openReadingPipe</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">address</span><span class="p">);</span>
</code></pre></div></div>
<p>Le premier argument est le numéro du flux. Vous pouvez créer jusquà 6 flux qui répondent à différentes adresses. Nous avons créé uniquement ladresse pour le numéro de flux 0. Le deuxième argument est ladresse à laquelle le flux réagira pour collecter les données.</p>
<p>Létape suivante consiste à définir le module en tant que récepteur et à commencer à recevoir des données. Pour ce faire, nous utilisons la fonction <code class="language-plaintext highlighter-rouge">radio.startListening()</code>. À partir de ce moment, le modem attend les données envoyées à ladresse spécifiée.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//Set module as receiver</span>
<span class="n">radio</span><span class="p">.</span><span class="n">startListening</span><span class="p">();</span>
</code></pre></div></div>
<p>Dans la fonction de boucle: Lesquisse vérifie si des données sont arrivées à ladresse à laide de la méthode <code class="language-plaintext highlighter-rouge">radio.available()</code> . Cette méthode renvoie la valeur TRUE si des données sont disponibles dans la mémoire tampon.</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="n">radio</span><span class="p">.</span><span class="n">available</span><span class="p">())</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="n">text</span><span class="p">[</span><span class="mi">32</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
<span class="n">radio</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="o">&amp;</span><span class="n">text</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">text</span><span class="p">));</span>
<span class="n">Serial</span><span class="p">.</span><span class="n">println</span><span class="p">(</span><span class="n">text</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Si les données sont reçues, un tableau de 32 caractères rempli de zéros est créé (plus tard, le programme le remplira avec les données reçues). Pour lire les données, nous utilisons la méthode <code class="language-plaintext highlighter-rouge">radio.read (&amp; text, sizeof (text))</code> . Cela va stocker les données reçues dans notre tableau de caractères.</p>
<p>À la fin, nous imprimons simplement le message reçu sur le moniteur série. Si vous avez tout fait correctement et quil ny a pas derreur dans les connexions, vous devriez voir quelque chose comme ceci dans votre moniteur série. <br />
<img src="/images/nRF24L01-Transceiver-RF24-Library-Sketch-Output-on-Serial-Monitor.png" alt="" /><br />
<em>nRF24L01 + sortie de lémetteur-récepteur sur le moniteur série</em></p>
<h2 id="amélioration-de-la-portée-du-module-émetteur-récepteur-nrf24l01-">Amélioration de la portée du module émetteur-récepteur nRF24L01 +</h2>
<p>Un paramètre clé pour un système de communication sans fil est la plage de communication. Dans de nombreux cas, cest le facteur décisif pour choisir une solution RF. Discutons donc de ce que nous pouvons faire pour améliorer la portée de notre module.</p>
<h3 id="réduire-le-bruit-dalimentation">Réduire le bruit dalimentation</h3>
<p>Un circuit RF qui génère un signal RF est très sensible au bruit de lalimentation. Sil nest pas contrôlé, le bruit de lalimentation peut réduire considérablement la portée que vous pouvez obtenir.</p>
<p>À moins que la source dalimentation ne soit une batterie autonome, il y a de fortes chances pour quil y ait du bruit associé à la génération de lénergie. Pour éviter que ce bruit ne pénètre dans le système, il est conseillé de placer un condensateur de filtrage de 10 µf sur la ligne d alimentation , aussi près que possible du module nRF24L01 +.</p>
<p>Pour vous en sortir le plus facilement, utilisez un module dadaptateur très économique pour nRF24L01.<br />
<img src="/images/nRF24L01-5V-Power-Adapter.png" alt="" /><br />
<em>nRF24L01 + adaptateur</em><br />
Le module adaptateur dispose dun connecteur femelle à 8 broches pour vous permettre de brancher votre module nRF24L01. Il peut accueillir à la fois le module dont nous avons parlé précédemment, celui avec antenne intégrée et lautre avec antenne externe (PA / LNA). Il possède également un connecteur mâle à 6 broches pour les connexions SPI et Interrupt et un connecteur à 2 broches pour lalimentation.</p>
<p>Le module adaptateur possède son propre régulateur de tension de 3,3 volts et un ensemble de condensateurs de filtrage, ce qui vous permet de lalimenter avec une alimentation de 5 volts.</p>
<h3 id="changer-la-fréquence-de-votre-canal">Changer la fréquence de votre canal</h3>
<p>Lenvironnement extérieur est une autre source potentielle de bruit pour un circuit RF, en particulier si vous avez des réseaux voisins fixés sur le même canal ou des interférences provenant dautres composants électroniques.</p>
<p>Pour éviter que ces signaux ne causent des problèmes, nous vous suggérons d<u>**utiliser les 25 canaux les plus élevés de votre module nRF24L01 +**</u>. La raison en est que le WiFi utilise la plupart des canaux inférieurs.</p>
<h3 id="taux-de-données-inférieur">Taux de données inférieur</h3>
<p>Le nRF24L01 + offre la plus haute sensibilité de récepteur à une vitesse de 250 Kbits/s, soit -94dBm. Cependant, à un débit de 2 Mbits/s, la sensibilité du récepteur chute à -82dBm. Si vous parlez cette langue, vous savez que le récepteur à 250 Kbps est près de 10 fois plus sensible que celui à 2 Mbps.<br />
Cela signifie que le récepteur peut décoder un signal 10 fois plus faible.</p>
<blockquote>
<p><strong>Que signifie sensibilité du récepteur (Rx)?</strong><br />
La sensibilité du récepteur est le niveau de puissance le plus bas auquel le récepteur peut détecter un signal RF. Plus la valeur absolue du nombre négatif est grande, meilleure est la sensibilité du récepteur. Par exemple, une sensibilité du récepteur de -94 dBm est préférable à une sensibilité du récepteur de -82 dBm sur 12 dB.</p>
</blockquote>
<p>Donc, réduire le débit de données peut considérablement améliorer la portée que vous pouvez atteindre. En outre, pour la plupart de nos projets, une vitesse de 250 Kbps est plus que suffisante.</p>
<h3 id="puissance-de-sortie-supérieure">Puissance de sortie supérieure</h3>
<p>Le réglage de la puissance de sortie maximale peut également améliorer la portée de communication. Le nRF24L01 + vous permet de choisir lune des valeurs de puissance de sortie. 0 dBm, -6 dBm, -12 dBm ou -18 dBm. La sélection d une puissance de sortie de 0 dBm envoie un signal plus fort dans les airs.</p>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2020-08-04T00:00:00+02:00"><!-- start custom article footer snippet -->
<!-- end custom article footer snippet -->
<!--
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2020/08/03/syntaxe-markdown.html">Syntaxe markdown</a></div><div class="next"><span>SUIVANT</span><a href="/2020/08/04/Systemd_Path_Unit_pour_surveiller_les_fichiers_et_les_repertoire.html">Systemd Path Unit pour surveiller les fichiers et les répertoires</a></div></div></div>
</div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
$(function() {
var $this ,$scroll;
var $articleContent = $('.js-article-content');
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
$scroll = $(scroll);
$articleContent.find('.highlight').each(function() {
$this = $(this);
$this.attr('data-lang', $this.find('code').attr('data-lang'));
});
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
$this = $(this);
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
});
$articleContent.on('click', '.anchor', function() {
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
});
});
});
})();
</script>
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
<!-- end custom main bottom snippet -->
</div>
</div></div></div></div>
</div><script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $body = $('body'), $window = $(window);
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
var activeCount = 0;
function modal(options) {
var $root = this, visible, onChange, hideWhenWindowScroll = false;
var scrollTop;
function setOptions(options) {
var _options = options || {};
visible = _options.initialVisible === undefined ? false : show;
onChange = _options.onChange;
hideWhenWindowScroll = _options.hideWhenWindowScroll;
}
function init() {
setState(visible);
}
function setState(isShow) {
if (isShow === visible) {
return;
}
visible = isShow;
if (visible) {
activeCount++;
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
$root.addClass('modal--show');
$pageMain.scrollTop(scrollTop);
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
$window.on('keyup', handleKeyup);
} else {
activeCount > 0 && activeCount--;
$root.removeClass('modal--show');
$window.scrollTop(scrollTop);
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
$window.off('keyup', handleKeyup);
}
onChange && onChange(visible);
}
function show() {
setState(true);
}
function hide() {
setState(false);
}
function handleKeyup(e) {
// Char Code: 27 ESC
if (e.which === 27) {
hide();
}
}
setOptions(options);
init();
return {
show: show,
hide: hide,
$el: $root
};
}
$.fn.modal = modal;
});
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
// search panel
var search = (window.search || (window.search = {}));
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
true : window.useDefaultSearchBox ;
var $searchModal = $('.js-page-search-modal');
var $searchToggle = $('.js-search-toggle');
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
var modalVisible = false;
search.searchModal = searchModal;
var $searchBox = null;
var $searchInput = null;
var $searchClear = null;
function getModalVisible() {
return modalVisible;
}
search.getModalVisible = getModalVisible;
function handleModalChange(visible) {
modalVisible = visible;
if (visible) {
search.onShow && search.onShow();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
} else {
search.onShow && search.onHide();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
setTimeout(function() {
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
search.clear && search.clear();
window.pageAsideAffix && window.pageAsideAffix.refresh();
}, 400);
}
}
$searchToggle.on('click', function() {
modalVisible ? searchModal.hide() : searchModal.show();
});
// Char Code: 83 S, 191 /
$(window).on('keyup', function(e) {
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
modalVisible || searchModal.show();
}
});
if (useDefaultSearchBox) {
$searchBox = $('.js-search-box');
$searchInput = $searchBox.children('input');
$searchClear = $searchBox.children('.js-icon-clear');
search.getSearchInput = function() {
return $searchInput.get(0);
};
search.getVal = function() {
return $searchInput.val();
};
search.setVal = function(val) {
$searchInput.val(val);
};
$searchInput.on('focus', function() {
$(this).addClass('focus');
});
$searchInput.on('blur', function() {
$(this).removeClass('focus');
});
$searchInput.on('input', window.throttle(function() {
var val = $(this).val();
if (val === '' || typeof val !== 'string') {
search.clear && search.clear();
} else {
$searchBox.addClass('not-empty');
search.onInputNotEmpty && search.onInputNotEmpty(val);
}
}, 400));
$searchClear.on('click', function() {
$searchInput.val(''); $searchBox.removeClass('not-empty');
search.clear && search.clear();
});
}
});
})();
</script><div class="search search--dark">
<div class="main">
<div class="search__header">Recherche</div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div>
</div>
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
Annuler</button>
</div>
<div id="results-container" class="search-result js-search-result"></div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
noResultsText: '<p>Aucun résultat!</p>',
json: '/search.json',
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a>&nbsp;(Création {create})</li>'
})
</script>
</div></div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function scrollToAnchor(anchor, duration, callback) {
var $root = this;
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
callback && callback();
});
}
$.fn.scrollToAnchor = scrollToAnchor;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function affix(options) {
var $root = this, $window = $(window), $scrollTarget, $scroll,
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
hasInit = false, curState;
function setOptions(options) {
var _options = options || {};
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroll && (scroll = _options.scroll);
_options.disabled !== undefined && (disabled = _options.disabled);
$scrollTarget = $(scrollTarget);
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
$scroll = $(scroll);
}
function preCalc() {
top();
rootHeight = $root.outerHeight();
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
rootLeft = $root.offset().left;
}
function calc(needPreCalc) {
needPreCalc && preCalc();
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
rootBottomTop = scrollBottom - rootTop;
}
function top() {
if (curState !== 'top') {
$root.removeClass('fixed').css({
left: 0,
top: 0
});
curState = 'top';
}
}
function fixed() {
if (curState !== 'fixed') {
$root.addClass('fixed').css({
left: rootLeft + 'px',
top: 0
});
curState = 'fixed';
}
}
function bottom() {
if (curState !== 'bottom') {
$root.removeClass('fixed').css({
left: 0,
top: rootBottomTop + 'px'
});
curState = 'bottom';
}
}
function setState() {
var scrollTop = $scrollTarget.scrollTop();
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
fixed();
} else if (scrollTop < rootTop) {
top();
} else {
bottom();
}
}
function init() {
if(!hasInit) {
var interval, timeout;
calc(true); setState();
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState();
});
$window.on('resize', function() {
disabled || (calc(true), setState());
});
hasInit = true;
}
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions,
refresh: function() {
calc(true, { animation: false }); setState();
}
};
}
$.fn.affix = affix;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function toc(options) {
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
function setOptions(options) {
var _options = options || {};
_options.selectors && (selectors = _options.selectors);
_options.container && (container = _options.container);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroller && (scroller = _options.scroller);
_options.disabled !== undefined && (disabled = _options.disabled);
$headings = $(container).find(selectors).filter('[id]');
$scrollTarget = $(scrollTarget);
$scroller = $(scroller);
}
function calc() {
headingsPos = [];
$headings.each(function() {
headingsPos.push(Math.floor($(this).position().top));
});
}
function setState(element, disabled) {
var scrollTop = $scrollTarget.scrollTop(), i;
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
if (element) {
$activeCur = element;
} else {
for (i = 0; i < headingsPos.length; i++) {
if (scrollTop >= headingsPos[i]) {
$activeCur = $tocLi.eq(i);
} else {
$activeCur || ($activeCur = $tocLi.eq(i));
break;
}
}
}
$activeLast && $activeLast.removeClass('active');
($activeLast = $activeCur).addClass('active');
}
function render() {
if(!hasRendered) {
$root.append($tocUl);
$headings.each(function() {
var $this = $(this);
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
});
$tocLi = $tocUl.children('li');
$tocUl.on('click', 'a', function(e) {
e.preventDefault();
var $this = $(this);
scrolling = true;
setState($this.parent());
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
scrolling = false;
});
});
}
hasRendered = true;
}
function init() {
var interval, timeout;
if(!hasInit) {
render(); calc(); setState(null, scrolling);
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState(null, scrolling);
});
$window.on('resize', window.throttle(function() {
if (!disabled) {
render(); calc(); setState(null, scrolling);
}
}, 100));
}
hasInit = true;
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions
};
}
$.fn.toc = toc;
});
})();
/*(function () {
})();*/
</script><script>
/* toc must before affix, since affix need to konw toc' height. */(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window);
var $articleContent = $('.js-article-content');
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
var toc;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
function disabled() {
return $col2.css('display') === 'none' || !hasToc;
}
tocDisabled = disabled();
toc = $tocRoot.toc({
selectors: TOC_SELECTOR,
container: $articleContent,
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
tocDisabled = disabled();
toc && toc.setOptions({
disabled: tocDisabled
});
}, 100));
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window), $pageFooter = $('.js-page-footer');
var $pageAside = $('.js-page-aside');
var affix;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
affix = $pageAside.affix({
offsetBottom: $pageFooter.outerHeight(),
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
scroll: hasSidebar ? $('.js-page-main').children() : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
affix && affix.setOptions({
disabled: tocDisabled
});
}, 100));
window.pageAsideAffix = affix;
});
})();
</script><!---->
</div>
<script>(function () {
var $root = document.getElementsByClassName('root')[0];
if (window.hasEvent('touchstart')) {
$root.dataset.isTouch = true;
document.addEventListener('touchstart', function(){}, false);
}
})();
</script>
</body>
</html>